This repository was archived by the owner on Feb 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 410
Promise.all indexing issue when combining non-zone.js promisesΒ #1077
Copy link
Copy link
Closed
Description
When you use Promise.all for combining not only zone.js promises (e.g. WinJSPromise) you can fall into issue that Promise.all results into single element result.
Example of issue https://plnkr.co/edit/UO2QhIa5eeLm6tPAyAjt?p=preview.
Important part of the code(skipping WinJSPromise import) is this one:
let p1 = WinJSPromise.as(3);
let p2 = Promise.resolve(45);
Promise.all([p1, p2]).then(res => {
console.log(`Promise.all: `, res);
})
WinJSPromise.join([p1, p2]).then(res => {
console.log(`WinJSPromise.join: `, res);
});
The output from Promise.all is [45], where expected is [3, 45]. This works fine with native Promise.all.
Problem is in how index is counted in this implementation:
Lines 305 to 331 in c8c5990
| static all<R>(values: any): Promise<R> { | |
| let resolve: (v: any) => void; | |
| let reject: (v: any) => void; | |
| let promise = new this<R>((res, rej) => { | |
| resolve = res; | |
| reject = rej; | |
| }); | |
| let count = 0; | |
| const resolvedValues: any[] = []; | |
| for (let value of values) { | |
| if (!isThenable(value)) { | |
| value = this.resolve(value); | |
| } | |
| value.then( | |
| ((index) => (value: any) => { | |
| resolvedValues[index] = value; | |
| count--; | |
| if (!count) { | |
| resolve(resolvedValues); | |
| } | |
| })(count), | |
| reject); | |
| count++; | |
| } | |
| if (!count) resolve(resolvedValues); | |
| return promise; | |
| } |
Following update implementation fixes the issue (note the index variable missing in original version):
Promise.all = function (values: any): Promise<any> {
let resolve: (v: any) => void;
let reject: (v: any) => void;
let promise = new this((res, rej) => {
resolve = res;
reject = rej;
});
let count = 0;
let index = 0;
const resolvedValues: any[] = [];
for (let value of values) {
if (!(value && value.then)) {
value = this.resolve(value);
}
value.then(
((index) => (value: any) => {
resolvedValues[index] = value;
count--;
if (!count) {
resolve(resolvedValues);
}
})(index),
reject);
count++;
index++;
}
if (!count) resolve(resolvedValues);
return promise;
}
This issue was found and discussed a bit here
alexdima, wzhudev and lightrabbit
Metadata
Metadata
Assignees
Labels
No labels