Abhishek Rastogi
Abhishek Rastogi

Reputation: 189

Async function not executing properly after response is send

I wrote a file called deploy.js which uploads all the files of a folder to github via its API. It takes two arguments - accessToken of user and folder which you want to upload. I get the access token through passport-github. I have a main app.js file and the deploy.js is available by the variable deploy. App.js has a route /what which calls the deploy function. The problem is that the following code works.

app.get('/what', function(req, res) {
      //req.user.token contains the oauth token of the user
      deploy(req.user.token, folder, function() {
          res.send("completed");
      });
  });

But if I put res.send() outside of the callback, it doesn't execute fully.

app.get('/what', function(req, res) {
      deploy(req.user.token, folder, function() {
          console.log("deploy completed");
      }); 
      res.send("Work being done");
  })

Here is my deploy.js file which I wrote. I have used the npm-github library as a node wrapper around the native github API.

var distHelper = require('./dist.js');
var fs = require('fs');
var path = require('path');
var github = require('github');
var gh = new github();

module.exports = function(accessToken, folder, callback) {
    //Authenticating using the oauth accessToken received above
    gh.authenticate({ type:"oauth", token: accessToken});

    var fullPath = distHelper.distPath + "/" + folder;
    var eventName = folder.substr(folder.search("/") + 1);

    //the below function returns a list of all files in a directory recursively
    var walk = function(dir, done) {
        var results = [];
        fs.readdir(dir, function(err, list) {
            if (err) return done(err);
            var i = 0;

            (function next() {
                var file = list[i++];
                if (!file) return done(null, results);
                file = dir + '/' + file;
                fs.stat(file, function(err, stat) {
                    if (stat && stat.isDirectory()) {
                        walk(file, function(err, res) {
                            results = results.concat(res);
                            next();
                        });
                    } else {
                        results.push(file);
                        next();
                    }
                });
            })();
        });
    };
    //creating a repo

    gh.repos.create({name: 'b', auto_init: 1}, function(err, response) {
        if(err) {
            console.log(err);
        }

        walk(fullPath, function(err, results) {
            if(err) {
                console.log(err);
            }

            //Base64 encoding of a file
            function encode(file) {
                var bitmap = fs.readFileSync(file);
                return new Buffer(bitmap).toString('base64');
            }

            //Function which uploads file to the github one by one
            function doOne() {
                var elem = results.shift();
                var fileName = elem.substr(elem.search(eventName)+eventName.length + 1);
                console.log(fileName);
                gh.repos.createFile({owner: "princu7", repo: "b", path: fileName, message: "please work", content:encode(elem)}, function(err, res) {
                    if(err) {
                        console.log(err);
                    }
                    else {
                        console.log("got response");
                    }
                    if(results.length > 0) {
                        doOne();
                    }
                    else {
                        // when all files are finished uploading, then the below function is called
                        callback();
                    }
                });
            }
            doOne();
        });
    });
};

I have banged my head against the wall looking for the reasons but I haven't been able to find any. It might be something related to the closures but I am not really sure. I would really appreciate if someone would help. Thanks.

Upvotes: 0

Views: 93

Answers (1)

Heartbit
Heartbit

Reputation: 1836

You should use websocket as bellow:

  1. In your server. app.js

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
  
  socket.on('doplyment', (msg) => {
    socket.emit('deploying', 'I will notify you after deployment');
    setTimeout(function(){
      socket.emit('doployed', 'your request done.')
    }, 3000)
  });
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});

  1. Your client side.client.js

<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script>
        var socket = io();
        socket.on('connect', function(){
        
          socket.emit('doployment', 'I am wating');
          socket.on('deploying', function(mas){
            console.log(mas);
          });
          socket.on('deployed', function (msg) {
            console.log(msg);
          });
      })
</script>

Upvotes: 1

Related Questions