taylorhakes/promise-polyfill

Using promise in a 'for' loop behaves differently on IE11

Ldoppea opened this issue · 2 comments

Hi,

First, thank you for this polyfill. I started to use it 1 year ago and it helps a lot.

I would like to show you a code that behaves differently on chrome/ff/opera and IE11.

This behavior occurs when I use a promise inside a for loop. When using IE, the for index is not sent correctly in the promise context.

For example, the following code should loop from 0 to 3 and print the corresponding index.

var sequencer = Promise.resolve();
for (let i = 0; i <= 3; i++) {
    sequencer = sequencer.then(function () {
        console.log('current index :', i);
    });
}
sequencer = sequencer.then(function () {
    console.log('end loop');
});

In chrome, each loop occurrence prints the correct index.
Chrome output:

current index : 0
current index : 1
current index : 2
current index : 3
end loop

But in IE, the for loop ends before the first then being executed (which is normal behavior) so the index value reached its final value 3. Then all then are executed using this final value instead of the "current" value at the moment of their declaration.
IE11 output:

current index : 3
current index : 3
current index : 3
current index : 3
end loop

To fix that, I had to wrap the console.log inside a function that takes the index and keep it with its correct value until its execution.

var sequencer = Promise.resolve();
for (let i = 0; i <= 3; i++) {
    var next = function (index) {
        return function () {
            console.log('current index :', index);
        };
    };
    sequencer = sequencer.then(next(i));
}
sequencer = sequencer.then(function () {
    console.log('end loop');
});

Chrome output:

current index : 0
current index : 1
current index : 2
current index : 3
end loop

IE11 output:

current index : 0
current index : 1
current index : 2
current index : 3
end loop

As I found a workaround, I'm not blocked by this issue, but it makes the code harder to read.

Also this seems to behave correctly when using array.forEach().

Do you know if this may/should be fixed or if this is a limitation from IE11?

Thanks,

Ldoppea

Hi @Ldoppea, unfortunately this does not have to do with promise-polyfill. This has to do with the keyword let in the loop. It makes the index value bound in the loop. IE11 does not fully support the let keyword. I would recommend using a transpiler such as babel to make this behave as expected.

You can see the same thing issue in the following code. Chrome will work as expected, but IE11 won't.

for (let i = 0; i <= 3; i++) {
    setTimeout(function() {
        console.log(i);
    }, 0);
}

Here is more info about IE11 support for let. You can see it does not support it in loops.
https://kangax.github.io/compat-table/es6/#test-let_for/for-in_loop_iteration_scope

Woups I didn't notice that I was using let (i'm often switching between old js and modern js), but unfortunately the behavior is the same with var.

Thank's for your answer, I expected that IE11 was faulty and your answer confirms that 👍