glasspill
glasspill

Reputation: 1300

call async function for each array element of a promise result object, make changes and return this object

A Bluebird Promise returns an object that contains two arrays of objects, cars and contracts. Then, I want to iterate over the cars, call an asynchronous function and, based on the returned value, make some changes to the second array and return the initial result object with these changes. I can't figure out how to do this with promises. Or with async, for that matter. I feel like they should be nested promises, but i can;t get it to work at all.

the version with promises:

somePromise().then(function (result) {

    Promise.each(result.cars, function (car) {
        makeAsyncCall(car.id, function (err, resultArray) {
            if (err) {
                throw new Error();
            }

            result.contracts.forEach(function (contract) {
                if (resultArray.indexOf(contract.id) > -1) {
                    contract.car = car.id;
                }
            });
        });

    }).then(function (eachResult) {
        //eachResult is result.firstArray, which is not interesting.
        return result;
    });

}).then(function (result)) {
    //this gets called before my promise.each gets executed??
}

Can anyone give me a hint as to where my mistake is?

Upvotes: 0

Views: 1331

Answers (1)

Bergi
Bergi

Reputation: 664970

Have a look at my rules of thumb for promise development. The two specific points that apply to your code are:

  • promisify your async callback-taking functions before using them, specifically

    var makeCall = Promise.promisify(makeAsyncCall);
    
  • always return promises from your functions that do asynchronous things. This is especially true for callbacks, like the function() { Promise.each(…).then(…) } and the function() { makeAsyncCall(…) }.

With those, you should get to the following:

somePromise().then(function(result) {
    return Promise.each(result.cars, function(car) {
        return makeCall(car.id).then(function(resultArray) {
            // a lookup structure of contracts by id could make this more efficient
            result.contracts.forEach(function (contract) {
                if (resultArray.indexOf(contract.id) > -1)
                    contract.car = car.id;
            });
        });
    }).return(result);
}).…

Upvotes: 1

Related Questions