Creating Promises for ... a loop instead of forEach?

I want to execute an array from Promises in parallel, and then wait for all Promises to complete.

It works:

var promises = [];

objects.forEach(function(object) {

    let promise = new Parse.Promise.as()
    .then(
        function() {
            return destroy(object);
        }
    );

    promises.push(promise);
});

return Parse.Promise.when(promises);

But if I use for (object of objects) {...}instead objects.forEach(function(object) {...});, this will not work. For each Promise in the array, it destroy(object);runs on the first object in the array:

var promises = [];

for (object of objects) {

    let promise = new Parse.Promise.as()
    .then(
        function() {
            return destroy(object);
        }
    );

    promises.push(promise);
});

return Parse.Promise.when(promises);

Why is this?

+4
source share
2 answers

Yes, you forgot to declare the variable objectas local to the loop body (see also canonical explanation ):

var promises = [];
for (let object of objects) {
//   ^^^
    promises.push(new Parse.Promise.as().then(function() {
        return destroy(object);
    }));
}
return Parse.Promise.when(promises);

Of course you shouldn't do this either, just use map:

var promises = objects.map(function(object) {
    return new Parse.Promise.as().then(function() {
        return destroy(object);
    });
});
return Parse.Promise.when(promises);
+4
source

Edit: , , . .

@Bergi, Promises objects, .map(). , :

const getPromises = (objects) => {
  return objects.map(object => new Parse.Promise.as()
    .then(() => {
      return destroy(object);
    })
  );
}
// No 'temp' array needed, and most important: promise variables aren't 'lost'

// Then you can similarly use this pattern:
return Parse.Promise.when(getPromises(objects));
// Or this:
return Promise.all(getPromises(objects));

() , , .:)


for Array.forEach. .forEach(), , , for loops. , 99,99% . . .

.map() , , 1:1 20:20, Array , 20: 1 (: 20 1 ):

.map    - use for 1:1 array transforms, as @bergi suggests.
.reduce - useful for transforming 1 array into ANYTHING else. Need a sum or subtotal? Or results grouped by day? Use .reduce().
.filter - return only items which result in a `true` result
.find   - use to avoid full array scans when only 1 item must be returned. 
.some   - exit array scan returning true at first opportunity

let downloadedMsgs  = emails.map(m => downloadBody(m))
let recipientsCount = emails.reduce((count, m) => count + m.to.length, 0)
let onlyRecentMsgs  = emails.filter(m => m.isNew)
let aRecentMsg      = emails.find(m => m.isNew)
let hasNewMessage   = emails.some(m => m.isNew)
// (Notice last 3 identical predicate fn with different uses: aka pluripotency)

- Promises! , 100 , HTTP- ( ). Promises.

0

Source: https://habr.com/ru/post/1680817/


All Articles