12

Say if I have a structure in Node.js shown below:

for (i = 0; i < 50; i++) {
    //Doing a for loop.
}

function after_forloop() {
    //Doing a function.
}

after_forloop();

So how could I make sure the after_forloop() function is fired after the forloop is completed?

In case if you want to see what I am actually working on:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

var proxyChecker = require('proxy-checker');
var fs = require('fs');

function get_line(filename, line_no, callback) {
    fs.readFile(filename, function (err, data) {
        if (err) throw err;
        var lines = data.toString('utf-8').split("\n");
        var firstLineBreak = data.toString('utf-8').indexOf("\n");
        var originalText = data.toString('utf-8');
        var newText = originalText.substr(firstLineBreak + 1);
        if(+line_no > lines.length){
            return callback('File end reached without finding line', null);
        }

        callback(null, lines[+line_no], newText);
    });
}


for (i = 0; i < 50; i++) {
    get_line('proxy_full.txt', i, function(err, line, newText){
        fs.appendFile('proxy.txt', line + '\n', function (err) {
            if (err) throw err;         
        });     
        fs.writeFile('proxy_full.txt', newText, function (err) {
            if (err) throw err;
        });
    })
}

after_forloop();

function after_forloop() {
    proxyChecker.checkProxiesFromFile(
        // The path to the file containing proxies
        'proxy.txt',
        {
            // the complete URL to check the proxy
            url: 'http://google.com',   
            // an optional regex to check for the presence of some text on the page
            regex: /.*/
        },
        // Callback function to be called after the check
        function(host, port, ok, statusCode, err) {
            if (ok) {
                console.log(host + ':' + port);
                fs.appendFile('WorkingProxy.txt', host + ':' + port + '\n', function (err) {
                    if (err) throw err;             
                });
            }                   
        }
    );

    setTimeout(function(){
        fs.writeFile('proxy.txt', "", function (err) {
            if (err) throw err;
        });
        console.log('Proxy Check Completed.')
        process.exit(1); 
    }, 5000);
}

Basically I like to allow the node server run 50 test on a list proxy servers at a time (within five seconds). And then the server should save the working proxies to a new file.

8
  • Execute it after the loop? Note you forgot to declare i. Commented Jan 13, 2015 at 2:51
  • 9
    By "after the for loop is completed" you probably mean "after all the asynchronous activity started in the for loop is completed", right? Commented Jan 13, 2015 at 2:51
  • I'm not getting what special here, just call that after for loop finished. Commented Jan 13, 2015 at 2:51
  • code usually runs top-down, but if it's not, you can make sure i is 50... Commented Jan 13, 2015 at 2:55
  • can you show the content of for loop. Commented Jan 13, 2015 at 2:57

7 Answers 7

10

Maybe this helps:

var operationsCompleted = 0;
function operation() {
    ++operationsCompleted;
    if (operationsCompleted === 100) after_forloop(); 
}
for (var i = 0; i < 50; i++) {
    get_line('proxy_full.txt', i, function(err, line, newText){
        fs.appendFile('proxy.txt', line + '\n', function (err) {
            if (err) throw err;
            operation();
        });     
        fs.writeFile('proxy_full.txt', newText, function (err) {
            if (err) throw err;
            operation();
        });
    })
}

Admittedly this isn't an elegant solution. If you're doing a whole lot of this you might want to check out something like Async.js.

Sign up to request clarification or add additional context in comments.

Comments

10

If you're doing any async operation in the for loop, you can simply keep it like

function after_forloop() {
// task you want to do after for loop finishes it's execution
}


 for (i = 0; i < 50; i++) {
 //Doing a for loop.

 if(i == 49) {
  after_forloop() // call the related function
 }
}

Still in node.js, instead of making use of for loops with asynchronous functions, you should see the async module. Here's Async.js or you can consider using recursion too.

Comments

8

If there is no magic happening then it should be straight forword.

Function:-

function after_forloop() {
    //Doing a function.
}

For Loop:-

for (i = 0; i < 50; i++) {
    //Doing a for loop.
}
for (i = 0; i < 50; i++) {
    //Doing another for loop.
}
after_forloop();

This will call after_forloop just after both for loops finishes. Because for loop is a blocking call, calling of after_forloop() has to wait.

Note:- If you are doing some async task in for loops then the function will be called after loop finished, but the work you are doing in loops might not finished by the time of calling function.

6 Comments

Great! What happen if I have multiple for loops, will it wait for all the for loops to complete?
@AeroWindwalker Yes the line will be called after for loop finished, because for loop is a sync task, it will blocking.
I think Nodejs isn't letting for loop running as a sync task. For example if I let the for loop to create a file with 50 lines, then having a function output the file, it will only output 1 or 2 lines (sometimes no line at all).
@AeroWindwalker you should probably forgot to read the note part of answer. I told you if you are doing some async task in for loop that might not finished.
Interesting! What would be the solution to it if I am doing asyn tasks in the forloop?
|
4

You can handle the last iteration of the for loop with a conditional checking index.

for(let i = 0; i < 10; i++){
  if(i == 10 - 1){
    your_function();
  }
}

1 Comment

I use this pattern, it works well. Also, I can make it dynamic with array.length.
2

use the Async module, Its easy and best.

async.each(array, function (element, callback) {
                        callback()
                    }, async function (err) {
                       console.log("array ends")
                    });

Comments

1

Simplest one!

try {
  for (i = 0; i < 50; i++) {
    //Doing a for loop.
  }
} finally {
  after_forloop();
}

Comments

0

I had this problem and created a function using setTimeout to repeatedly check every half second whether the for loop was completed before calling the function to run after the for loop completed:

function forLoopFunction() {
    // any other function code
    for loop {
      // body of for loop
    }
    checkForLoopComplete();
}
function checkForLoopComplete() {
  if (condition which indicates for loop is complete) {
    // call function to run on for loop complete
    functionOnForLoopComplete();
  } else {
    setTimeout(checkForLoopComplete, 500);
  }
}

function functionOnForLoopComplete() {
    // function code
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.