使用扩展将Promise内置子类化

问题描述

我想将.container { display: flex; justify-content: space-between; } .conatiner_Box { position: relative; width: 300px; height: 150px; border: 1px solid; display: flex; -webkit-Box-pack: center; justify-content: center; -webkit-Box-align: center; align-items: center; position: relative; border-left: 5px solid rgb(232,159,42); margin: 0px auto; overflow: hidden; } .image-Box { width: 100%; height: 100%; position: absolute; left: 0px; top: 0px; bottom: 0px; right: 0px; transition: all 0.1s linear 0s; }方法添加到内置<div class="container"> <div class="conatiner_Box"> <img src="https://i.ibb.co/HP3tksz/image1.jpg" class="image-Box"> </div> <div class="conatiner_Box"> <img src="https://i.ibb.co/Jz9cW7W/image2.jpg" class="image-Box"> </div> </div>的子类中。为什么这不起作用?

cancel

答案是Promise吗?

解决方法

问题在于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的深入研究可能值得。

,

实际上,then方法返回当前Promise类的新实例,因此p.cancel方法将在返回的Promise上定义,但它引用链中的最后一个Promise( catch链)。 取消承诺比仅拒绝链中的第一个承诺要困难得多。至少,您需要拒绝链中最深的未决承诺,并清理内部长期操作,例如请求,流,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();