1

I have an array of promises, I use $q.all to execute all the promises then I do an action, somehow this action executed before the promises give answer back.

note: flightAPIService.getNearestAirports() return $http angular :

  this.getNearestAirports = function (dataObj) {
    console.log('Client::flight service:: get the nearest '+ dataObj.maxAirports+' airport for lat: '+dataObj.lat+'lng:'+dataObj.lng);

    return $http.post('/getNearestAirports', dataObj);

    //// the result return in JSON format (Server converted the response from XML to JSON)
    //answer looks like:
    //{"airportResponse":{"$":{"authorisedAPI":"true","processingDurationMillis":"119","success":"true"},"airports":[{"airports":[{"$":{"city":"Tel-aviv","country":"Israel","lat":"32.011389","lng":"34.886667","name":"Ben Gurion","timezone":"Asia/Jerusalem"},"code":["TLV"]}]}]}}
};

when the $q.all executes the promises (airportPromises) I expected that printing the table object will come after the promises are ready, but actually the table printed before the promise have answer:

  $q.all(airportPromises).finally(function(res){
            //return callback(null, table);
            console.log(table);
        },function(err){
            callback(err);
            return console.error('one promise error',err);
        })

Here all the code:

this.addAirportsToTable = function (table,callback) {
    var airportPromises = [];
   // var defered = $q.defer();
    this.whenFlightNeeded(table).then(function (result) {
        var table = result;
        for (let dayIndex = 0; dayIndex < table.length; dayIndex++) {
            if (table[dayIndex].flight.flight) {
                var origin = {
                    maxAirports: 3,
                    lat: table[dayIndex]['cityGoogleInf'][0].latitude,
                    lng: table[dayIndex]['cityGoogleInf'][0].longitude
                };
                var dist = {
                    maxAirports: 3,
                    lat: table[dayIndex + 1]['cityGoogleInf'][0].latitude,
                    lng: table[dayIndex + 1]['cityGoogleInf'][0].longitude
                };

                var promise1 = flightAPIService.getNearestAirports(origin).then(function (resultOriginAirport) {
                    table[dayIndex]['flight'].airport.push(resultOriginAirport.data);
                });

                var promise2 = flightAPIService.getNearestAirports(dist).then(function (resultDistAirport) {
                    table[dayIndex + 1]['flight'].airport.push(resultDistAirport.data);
                });

                airportPromises.concat([promise1,promise2]);
            }
        }
        $q.all(airportPromises).finally(function(res){
            //return callback(null, table);
            console.log(table);
        },function(err){
            callback(err);
            return console.error('one promise error',err);
        })
    });
    //return defered.promise;
}

Any idea how to make sure that all promises are done then to print the table?

in this screenshot we can see that the object table was printed then the debugger goes back again to finish the promise task: enter image description here

kimo
  • 1,864
  • 5
  • 23
  • 29
  • Are you sure that `airportPromises` is scoped correctly and isn't getting overwritten somehow by a second set of operations? What happens if you move it to be next to `var table = ...` ? – Darien Apr 26 '16 at 21:33
  • I would guess `promise.all(p1, p2, p3, p4)` – Redu Apr 26 '16 at 21:33
  • 2
    I think "finally" is supposed to come last and is like a try/catch/finally. Maybe you wanted ".then" or "allSettled" (extension)? I'm guessing based on http://stackoverflow.com/questions/19944922/what-happens-with-q-all-when-some-calls-work-and-others-fail – Nikki9696 Apr 26 '16 at 21:36
  • Can´t explain your error but normally you would use waiting for promises like this: $q.all(airportPromises).then(function(res){ console.log(table); },function(err){ callback(err); console.error('one promise error',err); }); Then instead of finally – kabaehr Apr 26 '16 at 21:36
  • using finally or then give the same results while debug, airportPromises array not override, anyway I moved it and it give the same results. – kimo Apr 26 '16 at 21:42

1 Answers1

3

I believe the issue is your concat.

concat does not modify the existing array but returns a new one. So your calling $q.all passing it an empty array therefore is resolves instantly.

From the MDN:

Note: Concatenating array(s)/value(s) will leave the originals untouched. Furthermore, any operation on the new array will have no effect on the original arrays, and vice versa.

Quick example: https://jsfiddle.net/bunc6zg9/


On a side note $q.all resolves with an array of the values of the promises its waiting on. So if you returned your table values in the .then's from your two promises you can build your table in the $.all's then. That way you don't have a variable global to your promise chain containing its state.

ste2425
  • 4,656
  • 2
  • 22
  • 37
  • Great input, fixed the issue @ste2425 I pushed all promises to 1 array: airportPromises.push(flightAPIService.getNearestAirports(origin).then(function (resultOriginAirport) { table[dayIndex]['flight'].airport.push(resultOriginAirport.data); })); – kimo Apr 26 '16 at 22:28