How to lock a function until the previous one is completed? nodejs

have a for loop with a dynamic value that can be small or large, I want one search call to be completed before the next one starts. how to do it? I read about process.nextTick and setImmediate, but I'm not sure how to use them in this context.

function search(x) { dns.resolve(x, function (err, addresses) { if (!err) { res.send("bad"); } else { res.send("good"); } }); } for(a = 0; a < queries.length; a++) { query = queries[a]; search(query); } 
+4
source share
3 answers

I usually just use event emitters to make it synchronous, so I can still work in an asynchronous environment. In my code below, whenever the DNS resolution completes, it throws an event that is listened to by the search function and lets you know how to start a new search. In addition, you will learn how to create your own emitters of events that are amazing.

If you want to make it asynchronous for a certain size of an array of domain names, you can create a denominator variable and use the module operator to send asynchronous chunks and only fire a synchronous event (to clear the asynchronization buffer) each time the module reaches 0.

 // program that uses event emitters to create sync code in an async env var dns = require('dns') //dns from core var eventEmitter = require('events').EventEmitter //Event Emitter from core var ee = new eventEmitter; //make an Event Emitter object var queries = ['yahoo.com','google.com','james.com']; ee.on('next', next_search); //create a listener for an event we define // our listening function that executes on our defined 'next' event function next_search() { search(queries[a]); if(queries.length == a) process.exit(0); ++a; } // the actual search function that uses DNS function search(x) { dns.resolve(x, function (err) { if (!err) { //res.send("bad"); console.log('bad: ' + x) ee.emit('next') } else { //res.send("good"); console.log('good: ' + x) ee.emit('next') } }); } // global variable to keep track of our name queue length var a = 0; // kick it all off next_search() 
+3
source

There are several libraries that can help you organize the execution of asynchronous code. Async is the one I use and eachSeries () is useful here:

 function search(x,callback) { dns.resolve(x, function (err, addresses) { if (!err) { res.send("bad"); } else { res.send("good"); } callback(err); }); } async.eachSeries(queries, function(query,callback) { search(query,callback); }, function(err) { if(err) { console.log("we had an error"); } } ); 

Note that Async will call the final callback as soon as one of the iterations has an error, so if you don't want to dwell on it, you need to call callback() in search() instead of callback(err) .

UPDATE (without using a library):

If you do not want to use the library, you can implement it like this:

 function searchInternal(queries, idx, callback) { if(idx === queries.length) { callback(); return; } dns.resolve(queries[idx], function (err, addresses) { if (!err) { res.send("bad"); } else { res.send("good"); } searchInternal(queries, idx+1, callback); }); } function searchAll(queries, callback) { searchInternal(queries, 0, callback); } searchAll(queries, function() { console.log("all done now"); }); 

Please note: this code is not tested and probably not the best implementation, but therefore we use libraries.

+6
source

I recently created a simpler abstraction called wait.for to call asynchronous functions in synchronization mode (based on node-fibers). It is located at:

https://github.com/luciotato/waitfor

Using wait.for , you can make calls to dns.resolve to execute sequentially.

wait.for allows you to call any standard async nodejs function, as if it were a synchronization function, without blocking the node event loop. You can encode sequentially when you need it.

using wait.for , your code will be:

 for(a = 0; a < queries.length; a++) { try { addresses = wait.for(dns.resolve,queries[a]); res.send('good'); } catch(err){ res.send('bad'); } }//end for 
+2
source

Source: https://habr.com/ru/post/1494167/


All Articles