Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to chain a variable number of promises in Q, in order?

Tags:

node.js

promise

q

I have seen Chaining an arbitrary number of promises in Q ; my question is different.

How can I make a variable number of calls, each of which returns asynchronously, in order?
The scenario is a set of HTTP requests, the number and type of which is determined by the results of the first HTTP request.

I'd like to do this simply.

I have also seen this answer which suggests something like this:

var q = require('q'),     itemsToProcess =  ["one", "two", "three", "four", "five"];  function getDeferredResult(prevResult) {   return (function (someResult) {     var deferred = q.defer();     // any async function (setTimeout for now will do, $.ajax() later)     setTimeout(function () {       var nextResult = (someResult || "Initial_Blank_Value ") + ".." + itemsToProcess[0];       itemsToProcess = itemsToProcess.splice(1);       console.log("tick", nextResult, "Array:", itemsToProcess);       deferred.resolve(nextResult);     }, 600);      return deferred.promise;   }(prevResult)); }  var chain = q.resolve("start"); for (var i = itemsToProcess.length; i > 0; i--) {     chain = chain.then(getDeferredResult); } 

...but it seems awkward to loop through the itemsToProcess in that way. Or to define a new function called "loop" that abstracts the recursion. What's a better way?

like image 842
Cheeso Avatar asked Jul 20 '13 01:07

Cheeso


People also ask

What is chaining in promises?

Promise chaining: Promise chaining is a syntax that allows you to chain together multiple asynchronous tasks in a specific order. This is great for complex code where one asynchronous task needs to be performed after the completion of a different asynchronous task.

Are Promise all results in order?

Yes, the values in results are in the same order as the promises .

Can Promise be chained?

Introduction to the JavaScript promise chainingThe callback passed to the then() method executes once the promise is resolved. In the callback, we show the result of the promise and return a new value multiplied by two ( result*2 ).

How many promises can Promise all handle?

all itself as a promise will get resolved once all the ten promises get resolved or any of the ten promises get rejected with an error.


1 Answers

There's a nice clean way to to this with [].reduce.

var chain = itemsToProcess.reduce(function (previous, item) {     return previous.then(function (previousValue) {         // do what you want with previous value         // return your async operation         return Q.delay(100);     }) }, Q.resolve(/* set the first "previousValue" here */));  chain.then(function (lastResult) {     // ... }); 

reduce iterates through the array, passing in the returned value of the previous iteration. In this case you're returning promises, and so each time you are chaining a then. You provide an initial promise (as you did with q.resolve("start")) to kick things off.

At first it can take a while to wrap your head around what's going on here but if you take a moment to work through it then it's an easy pattern to use anywhere, without having to set up any machinery.

like image 182
Stuart K Avatar answered Sep 16 '22 15:09

Stuart K