Closed Finesse closed 3 years ago
Opened a promise-polyfill PR: https://github.com/taylorhakes/promise-polyfill/pull/125
Looks like my PR was merged into promise-polyfill so I'll go ahead and close this :)
@benjamingr Amending promise-polyfill isn't enough. This is also required:
... and fake-timers to implement
originalSetTimeout
usingsetTimeout
only
This way fake-timers won't race with promise-polyfill
I make tests that run in different browsers (including IE 11) via Karma. IE doesn't support promises, so I include promise-polyfill. The following test case doesn't proceed in IE 11:
(Jasmine isn't required, any test runner can be used)
The promise polyfill uses the global
setImmediate
function, the fake-timers library mocks thesetImmediate
function and usesPromise
insidetickAsync
. What happens is thattickAsync
callsresolve
that calls the mockedsetImmediate
that doesn't resolve because fake-timers has locked it, i.e. fake-timers dead-locks itself.If I disable mocking
setImmediate
using thetoFake
parameter, thecallback
will be called only 1 time instead of 5. It happens because the promise insidedelayCall
gets resolved aftertickAsync
decides to exit, becausedelayCall
resolves several promises sequentially whiletickAsync
waits for new timers only during a singleoriginalSetTimeout
resolution. Since bothPromise
andoriginalSetTimeout
wait usingsetImmediate
,tickAsync
exists beforedelayCall
spawns a new timer. A solution is to makeoriginalSetTimer
wait longer than any number of promise-polyfill's _immediateFn calls. It can be achieved by implementingoriginalSetTimeout
withsetTimeout
instead ofsetImmediate
(becausesetImmediate
always resolves before anysetTimeout
).The ideal solution for all
toFake
values is to makepromise-polyfill
always use the originalsetImmediate
and fake-timers to implementoriginalSetTimeout
usingsetTimeout
only. If you agree with this change and want me to make a MR, let me know. I'll make an issue in thepromise-polyfill
repository for this change.At the moment I can fix the issue locally in my project by disabling
setImmediate
individually for fake-timers. It will both disable mockingsetImmediate
and will makeoriginalSetTimeout
not usesetImmediate
. The fix in my code example: