0

I am trying to enforce a few asynchronous functions in node.js, to execute synchronously. I am using async.series for that. Here's my code:

 async.series([
        function(callback){
            fs.truncateSync('rooms.txt', 0);
            console.log("function1 done");
            callback(null, 'one');
        },  
        function(callback){
            fs.truncateSync('sids.txt', 0);
            console.log("start loop");
            var count = 0;
            async.whilst(
                function () { return count <5 },
                function (callback) {
                    count++;
                    sid.generateSIDs; //---> PROBLEM!!
                    callback();
                },
                function (err) {
                }
            );
            var sids = fs.readFileSync('sids.txt').toString().split('\r\n');
            console.log("function2 done");
            callback(null, 'two');
        },
        function(callback){
            //lots of asynchronous callbacks
            callback(null, 'three');
        }
    ],
    function(err, results){
        // results is now equal to ['one', 'two', 'three'] 
    }); 

Everything is working as expected (sequentially) in the above code. But when I am adding the line, sid.generateSIDs;, marked as 'PROBLEM', everything is going for a toss! generateSIDs is a function inside an external node.js file called sid.js. It uses restify to post a couple of HTTP GETs asynchronously. Here is the code inside sid.js:

'use strict';

var requestify = require('requestify'); 
var fs = require('fs'); 
var response = "";
var sessionId="";   

function generateSIDs() {   
    //Request 1: Send Protocol Upgrade Request
    response = "";
    sessionId="";
            requestify.request('http://url.com', {
                method: 'GET',
                headers: {
                    'Host': 'given',
                    'Connection': 'keep-alive',
                    'Origin': 'given',
                    'Referer': 'given'
                },
                cookies: {
                    'Cookie': 'given'
                },
                dataType: 'json'        
            })
            .then(function(response) {
                // get the response body
                response = response.getBody();
                sessionId = "extracted from response";

                //Request 2: Set up the session
                requestify.request('url.com'+sessionId, {
                    method: 'GET',
                    headers: {
                        'Host': 'given',
                        'Connection': 'keep-alive',
                        'Origin': 'given',
                        'Referer': 'given'
                    },
                    cookies: {
                        'Cookie': 'given'
                    },
                    dataType: 'json'        
                })
                .then(function(response) {
                    fs.appendFile('sids.txt', sessionId+'\r\n', function (err) {
                        if (err) return console.tag("SERVER").log("file not opening: "+err);
                    });
                    console.log("file write done");
                });             
            }); 
};
exports.generateSIDs = generateSIDs();

From inside the async.series(), generateSIDs() is getting called once, generating a new sid, and then it is not iterating further. From the console.log() I could see that because of the asynchronous nature of the restify call, as soon as sid.generateSIDs() is called, before even one iteration of this function is finished, the third function(callback) in async.series() is getting triggered.

But, I want sid.generateSIDs() to run multiple times sequentially as per the while loop count. After these runs are done, then only I want third function(callback) to get executed. As you can understand from generateSIDs() code, I want multiple unique sid's to be created before the third function is called.

When I am running sid.js separately from command line (not in a loop)using node sid.js, each time it is running fine and creating a new sid for me.

I am new to node.js, and handling synchronous and asynchronous functions together in the same code, messes up my logic!! Can you please help me here?

kajarigd
  • 1,299
  • 3
  • 28
  • 46
  • `exports.generateSIDs = generateSIDs()` means it's only called once and only during `require`. Never anywhere else. What exactly did you intend with that? – slebetman Mar 19 '15 at 03:17
  • Oh! Is it? So, in the line marked as PROBLEM, it is not getting called again and again? Each run of generateSIDs() created a new sid for me. Inside the async.whilst() loop, I want to call this function multiple times, say 5 times, so that the 5 sequential call to generateSIDs(), will create 5 new unique sids for me. – kajarigd Mar 19 '15 at 03:20
  • Correct. Each time you call `generateSID` creates new sid. However, you only call it once. In javascript, adding `()` to a function calls it. And you only do that once in your code. – slebetman Mar 19 '15 at 04:04
  • Okay! How can i execute it multiple times? – kajarigd Mar 19 '15 at 04:15
  • Should I execute "node sid.js" using some system command inside the while? Is this doable? If so, how? – kajarigd Mar 19 '15 at 04:17

1 Answers1

0

I found a working solution! I removed the execution of sid.generateSIDs() from inside async.whilst() loop in async.series([]). Instead I added the async.whilst() inside sid.js itself,lobal variables local. and made a couple of g Now, this is working as expected! Here is my updated code:

Updated code inside async.series:

   },  
        function(callback){
            fs.truncateSync('sids.txt', 0);
            console.log("start loop");
            var count = 0;
            async.whilst(
                function () { return count <5 },
                function (callback) {
                    count++;
                    sid.generateSIDs(num); //---> FIXED!
                    callback();
                },
                function (err) {
                }
            );
            console.log("function2 done");
            callback(null, 'two');
        },

Updated sid.js:

'use strict';

var requestify = require('requestify'); 
var fs = require('fs');  

function genEachSIDs() {   
    //Request 1: Send Protocol Upgrade Request
    var response = ""; //NOTE! I made this var local from global
    var sessionId=""; //NOTE! I made this var local from global to avoid override of values from one instance by another

    //code inside requestify.request( below is exactly same as given in the question above.
    requestify.request(
        //same code as above 
    );
}
// adding the while loop here!
module.exports generateSIDs = function generateSIDs(num){
        var count=0;
        async.whilst(
            function () { return count <num; },
            function (callback) {
                count++;
                genEachSIDs();
                callback();
            },
            function (err) {
            }
        );
    }

I removed the line: var sids = fs.readFileSync('sids.txt').toString().split('\r\n'); from the 2nd function, because this again needs to wait till all sid creation are done.

kajarigd
  • 1,299
  • 3
  • 28
  • 46