【问题标题】:Subclassing the Promise built-in using extends使用 extends 子类化 Promise 内置
【发布时间】:2020-10-02 06:42:17
【问题描述】:

我想将cancel 方法添加到Promise 内置函数的子类中。为什么这不起作用?

class CancellablePromise extends Promise {
    constructor(executor) {
        let cancel = null
        super((resolve,reject) => {
            cancel = reject
            executor(resolve, reject)
        })
        this.cancel = cancel
    }
}

const p = new CancellablePromise((resolve) => setTimeout(resolve, 1000))
    .then(() => console.log('success'))
    .catch((err) => console.log('rejected', err))

p.cancel() // Uncaught exception

答案是Symbol.species吗?

【问题讨论】:

    标签: javascript ecmascript-6 promise es6-class cancellation


    【解决方案1】:

    问题在于 thencatchfinally 创建并返回一个 new 承诺,而他们创建和返回的新承诺没有 cancel方法就可以了。

    要解决此问题,您必须覆盖 then,以便将 cancel 从当前实例复制到新实例:

    class CancellablePromise extends Promise {
        constructor(executor) {
            let cancel = null;
            super((resolve,reject) => {
                cancel = reject;
                executor(resolve, reject);
            });
            this.cancel = cancel;
        }
    
        then(onFulfilled, onRejected) {
            const p = super.then(onFulfilled, onRejected);
            p.cancel = this.cancel;
            return p;
        }
    }
    
    const p = new CancellablePromise((resolve) => setTimeout(resolve, 1000))
        .then(() => console.log('success'))
        .catch((err) => console.log('rejected', err));
    
    p.cancel();

    您无需执行 catchfinally,它们都是使用对 then 的调用定义的(根据规范)。

    我应该注意到,关于可取消的承诺有很多细微差别,我没有详细讨论。 Ben Lesh 的 Domenic Denicola's old (now withdrawn) cancellable promises proposalthis article 可能值得深入阅读。

    【讨论】:

    • 并且不要忘记并非所有“thenables”都必须从 Promise 类实例化。
    • @Alnitak - 确实是的。我的做法是确保任何可能只是一个 thenable 的东西早晚通过Promise.resolve。 :-)
    • 继承充满了意外的复杂性,它是一个看似高级的功能,不是吗?
    【解决方案2】:

    其实then方法返回的是当前promise类的一个新实例,所以p.cancel方法会定义在返回的promise上,但是它是指链中最后一个promise(catch链)。 取消一个 Promise 比仅仅拒绝链中的第一个 Promise 要困难得多。至少,您需要拒绝链中最深的未决承诺,并清理内部长期操作,如请求、流、setTimeout 等。 它们应该看起来像这样:

    import CPromise from "c-promise2";
    
    const delay= (ms, value)=>{
        return new CPromise((resolve, reject, {onCancel}) => {
            const timer = setTimeout(resolve, ms, value);    
            onCancel(() => {
                log(`clearTimeout`);
                clearTimeout(timer);
            })
        })
    }
    
    const p= delay(1000, 123).then(console.log);
    
    p.cancel();
    

    【讨论】:

      猜你喜欢
      • 2021-07-08
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 2018-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多