You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合p-cancelable与p-progress实现可取消的进度上报Promise

需求说明

需要实现同时支持执行进度上报、可主动取消的Promise,整合进度Promise、可取消Promise两类能力。单独实现任意单一能力都很简便,但组合二者时出现运行报错。
当前编写的代码可以正常上报执行进度,但运行时会抛出cancelablePromise.cancel is not a function错误。

报错原因

PProgress()调用后返回的是自身封装的Promise实例,不会自动透传内层PCancelable实例的cancel方法到外层。外层拿到的Promise实例实际为PProgress类型,本身不存在cancel方法,调用时就会触发该类型错误。

修复代码

调整doJobWithProgress函数逻辑,手动将内层可取消Promise的cancel方法绑定到外层带进度能力的Promise实例上即可,完整可运行代码如下:

import PCancelable from 'p-cancelable';
import PProgress  from 'p-progress';

const cancelablePromise = doJobWithProgress();

try {
    cancelablePromise.onProgress((progress) => {
        console.log('progress: ' + progress);
    });

    await sleep(500);

    cancelablePromise.cancel();

    const result = await cancelablePromise;

    console.log("result", result);
}
catch (error) {
    console.log("Main catch error: " + error);
}

function sleep(ms) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}

function doJobWithProgress() {
    let innerCancelable;
    const progressPromise = PProgress((progressCallback) => {
        innerCancelable = new PCancelable((resolve, reject, onCancel) => {
            let progress = 0;

            const interval = setInterval(() => {
                progress += 0.1;
                progressCallback(progress);
            }, 100);

            const timeout = setTimeout(() => {
                const result = 1;
                clearTimeout(timeout);
                clearInterval(interval);
                resolve(result);
            }, 1000);

            onCancel(() => {
                console.log('canceled');
                clearTimeout(timeout);
                clearInterval(interval);
            });
        });
        return innerCancelable;
    });
    // 将cancel方法透传到外层Promise实例
    progressPromise.cancel = innerCancelable.cancel.bind(innerCancelable);
    return progressPromise;
}
补充说明
  • 修复后返回的Promise同时支持onProgress进度监听、cancel主动取消两个核心能力,原有进度上报、取消时清理定时器的逻辑可正常运行
  • 主动取消后Promise会按可取消Promise的规范抛出取消错误,可被外层catch块正常捕获
  • 该实现完全符合Promise A+规范,支持then/catch/finally等原生Promise方法的链式调用

内容的提问来源于stack exchange,提问作者Rychu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 13:51:29