diff --git a/addons/web/static/src/core/utils/concurrency.js b/addons/web/static/src/core/utils/concurrency.js index b673cb6b8b4..9fa431c121a 100644 --- a/addons/web/static/src/core/utils/concurrency.js +++ b/addons/web/static/src/core/utils/concurrency.js @@ -154,3 +154,18 @@ export class Race { return this.currentProm; } } + +/** + * Deferred is basically a resolvable/rejectable extension of Promise. + */ +export class Deferred { + constructor() { + let resolve; + let reject; + const prom = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + return Object.assign(prom, { resolve, reject }); + } +} diff --git a/addons/web/static/tests/core/utils/concurrency_tests.js b/addons/web/static/tests/core/utils/concurrency_tests.js index bf61402ee69..b8bbc888188 100644 --- a/addons/web/static/tests/core/utils/concurrency_tests.js +++ b/addons/web/static/tests/core/utils/concurrency_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { Mutex, KeepLast, Race } from "@web/core/utils/concurrency"; +import { Deferred, Mutex, KeepLast, Race } from "@web/core/utils/concurrency"; import { nextTick, makeDeferred } from "../../helpers/utils"; QUnit.module("utils", () => { @@ -312,4 +312,18 @@ QUnit.module("utils", () => { assert.verifySteps(["ok (44)"]); assert.strictEqual(race.getCurrentProm(), null); }); + + QUnit.test("Deferred: basic use", async function (assert) { + const def1 = new Deferred(); + def1.then((v) => assert.step(`ok (${v})`)); + def1.resolve(44); + await nextTick(); + assert.verifySteps(["ok (44)"]); + + const def2 = new Deferred(); + def2.catch((v) => assert.step(`ko (${v})`)); + def2.reject(44); + await nextTick(); + assert.verifySteps(["ko (44)"]); + }); }); diff --git a/addons/web/static/tests/helpers/utils.js b/addons/web/static/tests/helpers/utils.js index 8354eaafe65..0abdc2ee4da 100644 --- a/addons/web/static/tests/helpers/utils.js +++ b/addons/web/static/tests/helpers/utils.js @@ -2,9 +2,10 @@ import { browser } from "@web/core/browser/browser"; import { isMacOS } from "@web/core/browser/feature_detection"; +import { download } from "@web/core/network/download"; +import { Deferred } from "@web/core/utils/concurrency"; import { patch, unpatch } from "@web/core/utils/patch"; import { registerCleanup } from "./cleanup"; -import { download } from "@web/core/network/download"; const { App, onMounted, onPatched, useComponent } = owl; @@ -150,15 +151,7 @@ export async function nextTick() { } export function makeDeferred() { - /** @type {(value:any)=>void} */ - let resolve; - /** @type {(reason?:any)=>void} */ - let reject; - const prom = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - return Object.assign(prom, { resolve, reject }); + return new Deferred(); } function findElement(el, selector) {