手写支持取消机制的Promise链式调用

69 阅读1分钟

以下是实现支持取消机制的Promise链式调用的完整方案,结合Promise核心原理与取消控制逻辑:

一、核心实现原理

1.‌状态机控制

  • 通过pending/fulfilled/rejected三态管理异步流程

  • 取消时强制状态转为rejected并触发终止信号

2.‌链式调用基础

  • then方法返回新Promise实例实现链式衔接

  • 回调队列管理确保执行顺序

3.‌取消机制设计

  • 标志位法‌:通过外部变量控制执行中断

  • AbortController‌:适用于fetch等场景的标准化取消

  • Pending冻结‌:返回永久pending的Promise阻断链路

二、完整代码实现

class CancelablePromise{
    constructor(executor){
        this.state = "pending";
        this.value = undefined;
        this.reason = undefined;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
        this.isCancelled = false;
        const resolve = (value) =>{
            if(this.state !=='pending' || this.isCancelled) return ;
            this.state='fulfilled';
            this.value = value;
            this.onFulfilledCallbacks.forEach(fn =>fn());
        };
        
        const reject = (reason) =>{
            if(this.state !=='pending') return ;
            this.state = 'rejected';
            this.reason = reason;
            this.onRejectedCallbacks.forEach(fn =>fn());
        };
        try{
            executor(resolve,reject);

        }catch(err){
            reject(err);
        }
    }
    then(onFulfilled,onRejected){
        return new CancelablePromise((resolve,reject)=>{
            const wrappedOnFulfilled = ()=>{
                if(this.isCancelled) return reject(new Error('Promise cancelled'));
                try{
                    const x = onFulfilled?.(this.value);
                    resolve(x);
                }catch(e){
                    reject(e);
                }
            }
            const wrappedOnRejected = ()=>{
                try{
                    const x = onRejected?.(this.reason);
                    resolve(x)
                }catch(e){
                    reject(e)
                }
            }
            if(this.state ==='fulfilled'){
                setTimeout(wrappedOnFulfilled,0)
            }else if(this.state ==='rejected'){
                setTimeout(wrappedOnRejected,0)
            }else{
                this.onFullfilledCallbacks.push(wrappedOnFulfilled);
                this.onRejectedCallbacks.push(wrappedOnRejected)
            }
        })
    }
    cancel(){
        this.isCancelled = true;
        this.reject(new Error('Promise canceled by user'))
    }
}

三、关键功能说明

1.‌取消触发点

  • 调用cancel()方法后立即终止后续链式调用

  • 已进入执行队列的任务不会被中断(需配合AbortController实现)

2.‌异常处理

  • 取消操作自动触发reject传播至最近catch节点

  • 支持自定义取消错误类型识别

3.‌链式兼容性

  • 保持与原生Promise相同的then/catch语法 

  • 支持async/await语法糖调用

四、使用示例

const p = new CancelablePromise(resolve => {
  setTimeout(() => resolve('Done'), 1000);
})
.then(console.log)
.catch(err => console.log('Error:', err.message));

// 取消执行
setTimeout(() => p.cancel(), 500); 
// 输出: Error: Promise cancelled by user