Gary
Gary

Reputation: 395

JavaScript Promises - Waiting for resolution before moving on

I have a requirement to do the following:

  1. Get a list of "lines" by calling an internal function (getLines()).
  2. Select the first line, perform an action
  3. After the previous action finishes, select the next line and do the same action
  4. Repeat for all lines (3-20 depending on user)

I have the following code in place:

App.Lines = response.data;    
for (var _i = 0; _i < App.Lines.length; _i++) {
    var makeCallPromise = new Promise(
        function(resolve, reject) {
            Session.connection.ol.makeCall(App.Lines[_i], callBackFunction(response) {
                //this can take up to 30 seconds to respond...
                resolve(response.data);
            }, errorCallBackFunction(message) {
                reject(message.error);
            }, bareJid);
        }
    )
    makeCallPromise.then(function(fulfilled) {
        console.log("PROMISE WORKED!!!!!", fulfilled);
    })
    .catch(function(error) {
        console.log("PROMISE FAILED!!!!!", error);
    });
}

My hope was that the loop would wait to resolve the promise before it continued the loop, however, that's not the case. My question is whether or not it's possible to halt the loop until the resolution is complete. Note - I am using the bluebird JS library for promises. Thank you!

Kind Regards,

Gary

Upvotes: 0

Views: 1107

Answers (4)

alexmac
alexmac

Reputation: 19617

You should use Bluebird#each method:

.each(function(any item, int index, int length) iterator) -> Promise

Iterate over an array, or a promise of an array, which contains promises (or a mix of promises and values) with the given iterator function with the signature (value, index, length) where value is the resolved value of a respective promise in the input array. Iteration happens serially. If any promise in the input array is rejected the returned promise is rejected as well.

Promise.each(App.Lines, line => {
    return new Promise((resolve, reject) => {
        Session.connection.ol.makeCall(line, callBackFunction(response) {
            resolve(response.data);
        }, errorCallBackFunction(message) {
            reject(message.error);
        }, bareJid);
    })
    .then(fulfilled => console.log("PROMISE WORKED!!!!!", fulfilled))
    .catch(err => onsole.log("PROMISE FAILED!!!!!", err));
});

Upvotes: 0

sjahan
sjahan

Reputation: 5960

I don't know about bluebird, but you can do something like that to create some kind of for loop that waits for each promise to end before the next iteration.

Here is a generic example, it could certainly be optimized, it's just a quick attempt:

var i = 0;
var performAsyncOperation = function(operationNumber) {
    return new Promise(function(resolve, reject){
    console.log('Operation number', operationNumber);
    resolve();
  });
}

var chainAsyncOperations = function() {
    if(++i < 10) {
        return performAsyncOperation(i).then(chainAsyncOperations);
    }
};
performAsyncOperation(i).then(chainAsyncOperations);

Hoping this will help you ;)

Upvotes: 1

Olivier Boiss&#233;
Olivier Boiss&#233;

Reputation: 18173

This Use Case perfectly matches the ES7 feature async await, If you have the possibility to transpile your code using babeljs, you could refactor your function like this :

function createPromise(line) {
    return new Promise(
       function(resolve, reject) {
          Session.connection.ol.makeCall(line, callBackFunction(response) {
              //this can take up to 30 seconds to respond...
              resolve(response.data);
          }, errorCallBackFunction(message) {
              reject(message.error);
          }, bareJid);
       }
    );
}

App.Lines = response.data;

async function main() {
    for (var _i = 0; _i < App.Lines.length; _i++) {
        try {
           var result = await createPromise(App.Lines[_i]);
           console.log(result);
        } catch (err) {
           console.log(err);
        }
    }
}

main().then(function() {
    console.log('finished');
});

Upvotes: 0

marvel308
marvel308

Reputation: 10458

You can use Promise.each() provided by bluebird, It would traverse an array serially and wait for them to resolve before moving to the next element in the array

Upvotes: 0

Related Questions