0

I am trying to call a promise inside a for loop. I need the call to have the relevant loop item. I read a bit about it but still can't seem to figure the correct way to do it.

var params;
var  identifylayers =["parcels", "lots", "gasstation"];
for (i = 0; i < identifylayers.length; i++)
{
        lname = identifylayers[i];

    govmap.intersectFeatures()
    .then(function (e)
    {
       alert( lname);
    });

}

Running the function returns: gasstation,gasstation,gasstation

I want it to return: parcels, lots, gasstation

What am I doing wrong?

JJJ
  • 32,902
  • 20
  • 89
  • 102

2 Answers2

0

Its the async devil of JavaScript lurking in your code. :D

Observe it like this -

  1. As soon as your program flow encounter a promise call which here is - intersectFeatures().then(fn (){}), it know that this call will eventually finish so the program flow will never attempt to execute the callback passed to .then() right at the moment instead it will keep it safe with itself and set a reminder that as soon as the intersectFeatures is finished it need to execute the callback passed to .then().
  2. Next thing to notice is how the .then(callback) will have access to lname. Its by closures. So
  3. Another important thing to notice is that this whole stuff is inside a loop. Your loop has no idea whether the code its iterating on is synchronous or asynchronous. Its only task is to iterate. And as we mentioned before in Point - 1 the .then(callback) will not be executed right at the moment. So by the time then .then(callback) will be executed your loop would already be finished and at the end of iteration lname holds gasstation. Hence your .then(callback) only print gasstation

Solution:

This is really old JS solution of iterating the async code and still ensuring the proper variable access using closures -

    for (i = 0; i < identifylayers.length; i++)
    {
        lname = identifylayers[i];
        (function (lname) {
            govmap.intersectFeatures()
                  .then( function () {
                      alert(lname);
                  } )
        })(lname);

    }

This utilises the benefit of functional scope of a variable and idea of closures. Google it to find more information.

Its also referred to as befriending closures, I just made that up :D

Cheers!

Himanshu Singh
  • 970
  • 2
  • 6
  • 18
  • have heared about closures but never understood it fully .it works .thanks a lot Himanshu . – Lord Corwin Aug 30 '18 at 12:13
  • Cheers buddy :D Read [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) to know more about closures and practical use case. – Himanshu Singh Aug 30 '18 at 17:48
-1

Define lname in the loop. Currently it is the same instance for each iteration, so it gets overriden, and then the promise resolves and prints the last overwrite each time.

const lname = identifylayers[i];

It is getting overriden before the async code runs.

async function intersectFeatures() {
  return "OK"
}

var params;
var identifylayers = ["parcels", "lots", "gasstation"];
for (let i = 0; i < identifylayers.length; i++) {
  const lname = identifylayers[i];
  intersectFeatures()
    .then(function(e) {
      alert(lname);
    });

}
Steven Spungin
  • 27,002
  • 5
  • 88
  • 78