问题描述:

I have a couple of asynchronous requests that fetch some data from a url. The problem I am having is that I actually want to delay sending the json response until all requests have come back. The code looks something like this:

getFirstStuff(callback) //imagine this is async

{

console.log('gettingFirstStuff');

callback(stuff);

}

function getFurtherStuff(callback) //imagine this is async

{

console.log('gettingFurtherStuff');

callBack(thing);

}

function getStuff(callBack)

{

getFirstStuff(function(stuff) // async

{

// stuff is an array of 3 items

stuff = stuff.map(function(item) // map is synchronous

{

// For each item in stuff make another async request

getFurtherStuff( function(thing) { // this is also async

stuff.thing = thing;

});

return item;

});

callback(stuff);

});

}

router.get('/getstuff', function(req, res, next) {

getStuff(function(stuff)

{

console.log('finished stuff');

// RETURN RESPONSE AS JSON

res.json(stuff);

});

});

The output will be:

gettingFirstStuff

finished stuff

gettingFurtherStuff

gettingFurtherStuff

gettingFurtherStuff

but it should be:

gettingFirstStuff

gettingFurtherStuff

gettingFurtherStuff

gettingFurtherStuff

finished stuff

I understand that the reason is that getFurtherStuff is async and item will be returned from map before the getFurtherStuff async calls are back with a result. My question is, what is the standard way to wait for these calls to finish before calling the final callback 'callback(stuff)'

网友答案:

There are a bunch of ways to solve this problem. Libraries like async and queue would probably be the best choice, if you have no problem adding dependencies.

The easiest option without external libs is just to count the async jobs and finish when they're all done:

// assuming stuff is an array
var counter = 0;
var jobCount = stuff.length;

// wrap callback in one that checks the counter
var doneCallback = function() {
    if (counter >= jobCount) {
        // we're ready to go
        callback(stuff);
    }
};

// run jobs
stuff.map(function(item) {
    getFurtherStuff(item, function(itemThing) {
        // process async response
        stuff.thing = itemThing;
        // increment counter;
        counter++;
        // call the wrapped callback, which won't fire
        // until all jobs are complete
        doneCallback();
    });
});
网友答案:
npm install async

You would then simply throw your functions in to an async.parallel()

More info at https://www.npmjs.com/package/async

相关阅读:
Top