简体   繁体   中英

Proper use of for loops and promises

Looping over an array with x amount of items I am executing a promise inside the loop. The promise takes a parameter that relies on the incrementing value (ie. The current value of i .

I want to know what the correct/best way of implementing this functionality so that I am ensuring that the correct value of i is being parsed to the promise.

This is an example of the structure of the code.

for (var i = 0; var < array.length; ++i) {
   SomePromise.get(i).then(function(result) {
      console.log(result);
   }).catch()......
}

As you would gather i might/will end up being the final value of increments took before being parsed to the promise. That is that the loop has executed to the end before the promise is executed leaving the value of i to be whatever the length of the array is.

As you would gather i might/will end up being the final value of increments took before being parsed to the promise.

Not the way you've used i . This code:

SomePromise.get(i)...

...takes the value of i and passes it into get . Once get receives it, the value is not in any way connected to the i variable, so it doesn't matter what get does with it.

The issue you're thinking of (discussed by this question and its answers ) would happen if you used i in the then callback. But where you're using it, passing it into a function as an argument, it doesn't happen because that's unrelated to the closure. The key thing, again, is that i 's value is passed into get , not some kind of reference to the i variable (JavaScript doesn't have any form of pass-by-reference, just closures).

In terms of passing the right i into the code and doing something with the result, that code is fine.


Here's a demonstration that it's fine as is (requires that your browser support Promise ):

 function getSomePromise(value) { return new Promise(function(resolve) { resolve(value); }); } var array = [1, 2, 3, 4]; for (var i = 0; i < array.length; ++i) { getSomePromise(i) .then(function(result) { var p = document.createElement("p"); p.innerHTML = "Result is " + result; document.body.appendChild(p); }); // catch omitted for brevity } 

...and a demonstration of how using i in the then callback would have the effect you're worried about (which is good or bad depending on your goals for the code):

 function getSomePromise(value) { return new Promise(function(resolve) { resolve(value); }); } var array = [1, 2, 3, 4]; for (var i = 0; i < array.length; ++i) { getSomePromise(i) .then(function(result) { var p = document.createElement("p"); p.innerHTML = "Result is " + result + ", i is " + i; document.body.appendChild(p); }); // catch omitted for brevity } 

Getting increasingly hypothetical and a bit far afield of the question, if you needed to use i in the then callback and wanted the then-current, not final, version, in this particular case you'd probably use array.forEach(function(entry, index) ...) and then use index , which wouldn't change:

 function getSomePromise(value) { return new Promise(function(resolve) { resolve(value); }); } var array = [1, 2, 3, 4]; array.forEach(function(entry, index) { getSomePromise(index) .then(function(result) { var p = document.createElement("p"); p.innerHTML = "Result is " + result + ", index is " + index; document.body.appendChild(p); }); // catch omitted for brevity }); 

But that's getting a bit far afield of your question.

If using a for loop is not a must, you may also consider Array.prototype.forEach .

array.forEach(function(arrayItem, i){
  SomePromise.get(i).then(function(result) {
    console.log(result);
  }).catch()......
});

In the realm of functional JavaScript, this works elegantly with Promise waiting:

Promise.all(array.map(function(arrayItem, i){
  return SomePromise.get(i).then(function(result) {
    console.log(result);
  }).catch()......
}));

Either way, by for-loops or by forEach/map, the integer i would be passed-by-value into the function, and thus would not be affected the increment in the loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM