Skip to content

Commit c3f9508

Browse files
committed
fix(race): concurrent next calls
1 parent 24330c0 commit c3f9508

File tree

1 file changed

+51
-34
lines changed

1 file changed

+51
-34
lines changed

src/execution/execute.js

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,43 +1774,60 @@ export class Dispatcher {
17741774
});
17751775
}
17761776
return new Promise((resolve) => {
1777+
let resolved = false;
17771778
this._subsequentPayloads.forEach((promise) => {
1778-
promise.then(() => {
1779-
// resolve with actual promise, not resolved value of promise so we can remove it from this._subsequentPayloads
1780-
resolve({ promise });
1781-
});
1782-
});
1783-
})
1784-
.then(({ promise }) => {
1785-
this._subsequentPayloads.splice(
1786-
this._subsequentPayloads.indexOf(promise),
1787-
1,
1788-
);
1789-
return promise;
1790-
})
1791-
.then(({ value, done }) => {
1792-
if (done && this._subsequentPayloads.length === 0) {
1793-
// async iterable resolver just finished and no more pending payloads
1794-
return {
1795-
value: {
1796-
hasNext: false,
1797-
},
1798-
done: false,
1779+
promise.then((payload) => {
1780+
if (resolved) {
1781+
return;
1782+
}
1783+
1784+
resolved = true;
1785+
1786+
if (this._subsequentPayloads.length === 0) {
1787+
// a different call to next has exhausted all payloads
1788+
resolve({ value: undefined, done: true });
1789+
return;
1790+
}
1791+
1792+
const index = this._subsequentPayloads.indexOf(promise);
1793+
1794+
if (index === -1) {
1795+
// a different call to next has consumed this payload
1796+
resolve(this._race());
1797+
return;
1798+
}
1799+
1800+
this._subsequentPayloads.splice(index, 1);
1801+
1802+
const { value, done } = payload;
1803+
1804+
if (done && this._subsequentPayloads.length === 0) {
1805+
// async iterable resolver just finished and no more pending payloads
1806+
resolve({
1807+
value: {
1808+
hasNext: false,
1809+
},
1810+
done: false,
1811+
});
1812+
return;
1813+
} else if (done) {
1814+
// async iterable resolver just finished but there are pending payloads
1815+
// return the next one
1816+
resolve(this._race());
1817+
return;
1818+
}
1819+
1820+
const returnValue: ExecutionPatchResult = {
1821+
...value,
1822+
hasNext: this._subsequentPayloads.length > 0,
17991823
};
1800-
} else if (done) {
1801-
// async iterable resolver just finished but there are pending payloads
1802-
// return the next one
1803-
return this._race();
1804-
}
1805-
const returnValue: ExecutionPatchResult = {
1806-
...value,
1807-
hasNext: this._subsequentPayloads.length > 0,
1808-
};
1809-
return {
1810-
value: returnValue,
1811-
done: false,
1812-
};
1824+
resolve({
1825+
value: returnValue,
1826+
done: false,
1827+
});
1828+
});
18131829
});
1830+
});
18141831
}
18151832

18161833
_next(): Promise<IteratorResult<AsyncExecutionResult, void>> {

0 commit comments

Comments
 (0)