[FIX] web: reject race promise when first promise rejects
The Race concurrency promise never settles if the first settled promise rejects and therefore you can't catch the rejected promise. closes odoo/odoo#104733 X-original-commit: 24cc8cdb440a5af944d82a25d98b0239e72e2625 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com> Signed-off-by: Lucas Lefèvre (lul) <lul@odoo.com>
This commit is contained in:
@@ -123,6 +123,7 @@ export class Race {
|
||||
constructor() {
|
||||
this.currentProm = null;
|
||||
this.currentPromResolver = null;
|
||||
this.currentPromRejecter = null;
|
||||
}
|
||||
/**
|
||||
* Register a new promise. If there is an ongoing race, the promise is added
|
||||
@@ -131,19 +132,26 @@ export class Race {
|
||||
* promise added to the race.
|
||||
*
|
||||
* @param {Promise} promise
|
||||
* @returns {Promise
|
||||
* @returns {Promise}
|
||||
*/
|
||||
add(promise) {
|
||||
if (!this.currentProm) {
|
||||
this.currentProm = new Promise((resolve) => {
|
||||
this.currentProm = new Promise((resolve, reject) => {
|
||||
this.currentPromResolver = (value) => {
|
||||
this.currentProm = null;
|
||||
this.currentPromResolver = null;
|
||||
this.currentPromRejecter = null;
|
||||
resolve(value);
|
||||
};
|
||||
this.currentPromRejecter = (error) => {
|
||||
this.currentProm = null;
|
||||
this.currentPromResolver = null;
|
||||
this.currentPromRejecter = null;
|
||||
reject(error);
|
||||
};
|
||||
});
|
||||
}
|
||||
promise.then(this.currentPromResolver);
|
||||
promise.then(this.currentPromResolver).catch(this.currentPromRejecter);
|
||||
return this.currentProm;
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -302,6 +302,104 @@ QUnit.module("utils", () => {
|
||||
assert.verifySteps(["ok (44) [2]", "ok (44) [3]"]);
|
||||
});
|
||||
|
||||
QUnit.test("Race: catch rejected promise", async function (assert) {
|
||||
const race = new Race();
|
||||
const def = makeDeferred();
|
||||
|
||||
race.add(def).catch((v) => assert.step(`not ok (${v})`));
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
def.reject(44);
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps(["not ok (44)"]);
|
||||
});
|
||||
|
||||
QUnit.test("Race: first promise rejects first", async function (assert) {
|
||||
const race = new Race();
|
||||
const def1 = makeDeferred();
|
||||
const def2 = makeDeferred();
|
||||
|
||||
race.add(def1).catch((v) => assert.step(`not ok (${v}) [1]`));
|
||||
race.add(def2).catch((v) => assert.step(`not ok (${v}) [2]`));
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
def1.reject(44);
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps(["not ok (44) [1]", "not ok (44) [2]"]);
|
||||
|
||||
def2.resolve();
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps([]);
|
||||
});
|
||||
|
||||
QUnit.test("Race: second promise rejects after", async function (assert) {
|
||||
const race = new Race();
|
||||
const def1 = makeDeferred();
|
||||
const def2 = makeDeferred();
|
||||
|
||||
race.add(def1).then((v) => assert.step(`ok (${v}) [1]`));
|
||||
race.add(def2).then((v) => assert.step(`ok (${v}) [2]`));
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
def1.resolve(44);
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps(["ok (44) [1]", "ok (44) [2]"]);
|
||||
|
||||
def2.reject();
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps([]);
|
||||
});
|
||||
|
||||
QUnit.test("Race: second promise rejects first", async function (assert) {
|
||||
const race = new Race();
|
||||
const def1 = makeDeferred();
|
||||
const def2 = makeDeferred();
|
||||
|
||||
race.add(def1).catch((v) => assert.step(`not ok (${v}) [1]`));
|
||||
race.add(def2).catch((v) => assert.step(`not ok (${v}) [2]`));
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
def2.reject(44);
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps(["not ok (44) [1]", "not ok (44) [2]"]);
|
||||
|
||||
def1.resolve();
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps([]);
|
||||
});
|
||||
|
||||
QUnit.test("Race: first promise rejects after", async function (assert) {
|
||||
const race = new Race();
|
||||
const def1 = makeDeferred();
|
||||
const def2 = makeDeferred();
|
||||
|
||||
race.add(def1).then((v) => assert.step(`ok (${v}) [1]`));
|
||||
race.add(def2).then((v) => assert.step(`ok (${v}) [2]`));
|
||||
|
||||
assert.verifySteps([]);
|
||||
|
||||
def2.resolve(44);
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps(["ok (44) [1]", "ok (44) [2]"]);
|
||||
|
||||
def1.reject();
|
||||
await nextTick();
|
||||
|
||||
assert.verifySteps([]);
|
||||
});
|
||||
|
||||
QUnit.test("Race: getCurrentProm", async function (assert) {
|
||||
assert.expect(7);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user