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

原生Promise外部resolve问题:jQuery Deferred重构求助

问题:将jQuery Deferred重构为原生Promise的困惑

我正在把一段基于jQuery Deferred的代码改写为原生Promise实现,原代码涉及将Deferred对象传递给多个函数,还用到了Deferred对象数组。改写时遇到了核心问题:在functionC里没法像jQuery Deferred那样直接调用Promise的resolve方法,尝试用Promise.resolve()又不确定能不能实现原代码中按索引触发resolve的效果,想找一个符合原逻辑的改写方案。

原jQuery Deferred代码

public functionA(){
    const dArray: Array<JQueryDeferred<{a:string}>> = [];
    // 其他逻辑
    functionB(dArray, /*其他参数*/);
}

private functionB(dArray: Array<JQueryDeferred<{a:string}>>, /*其他参数*/){
    // 其他逻辑
    for(var i=0;i<10;i++){
        dArray.push($.Deferred());
        var ele = dArray.length-1;

        functionC(dArray[ele], /*其他参数*/)
            .done((result: { a:string}) => {
                // 业务逻辑
            })
            .always(() => {
                // 额外逻辑
        });
    }
}

private functionC(d: JQueryDeferred<{a:string}>):JQueryDeferred<{a:string}>{
        if(/*某个条件*/){
           // 其他逻辑 
           d.resolve({ a: "completed" });
        }
    return d;
}

我尝试的原生Promise改写代码

public functionA(){
    const pArray: Array<Promise<{a:string}>> = [];
    // 其他逻辑
    functionB(pArray, /*其他参数*/);
}

private functionB(pArray: Array<Promise<{a:string}>>, /*其他参数*/){
    // 其他逻辑
    for(var i=0;i<10;i++){
        let resolvePromise;
        pArray.push(new Promise<{ a:string; }>(resolve => resolvePromise = resolve));
        var ele = pArray.length-1;

        functionC(pArray[ele], /*其他参数*/)
            .then((result: { a:string }) => {
                // 业务逻辑
            })
            .finally(() => {
                // 额外逻辑
        });
    }
}

private functionC(p: Promise<{a:string}>):Promise<{a:string}>{
        if(/*某个条件*/){
           // 其他逻辑 
           // 这里卡住了:Promise实例没有resolve方法
           // p.resolve({ a: "completed"}) 
           // 试过Promise.resolve({ a: "completed"}), 但不确定是否和原代码索引式resolve效果一致
        }
    return p;
}

解决方案

原生Promise和jQuery Deferred的核心差异在于:Promise实例本身没有resolve/reject方法,只有创建Promise时的执行器函数能拿到改变状态的resolve/reject函数。要复刻原代码的逻辑,需要把resolve函数和对应的Promise绑定后存入数组,让functionC能拿到resolve函数来触发状态变化。

修改后的完整代码

public functionA() {
    // 数组存储包含Promise和resolve方法的对象,对应原代码的Deferred数组
    const pArray: Array<{
        promise: Promise<{a:string}>,
        resolve: (value: {a:string}) => void
    }> = [];
    // 其他逻辑
    functionB(pArray, /*其他参数*/);
}

private functionB(pArray: Array<{promise: Promise<{a:string}>, resolve: (value: {a:string}) => void}>, /*其他参数*/) {
    // 其他逻辑
    for(let i = 0; i < 10; i++) {
        let resolveFn: (value: {a:string}) => void;
        // 创建Promise时保存resolve函数
        const promise = new Promise<{a:string}>(resolve => {
            resolveFn = resolve;
        });
        const deferredObj = { promise, resolve: resolveFn! };
        pArray.push(deferredObj);
        const ele = pArray.length - 1;

        // 将绑定好的对象传给functionC,复刻原代码传递Deferred的逻辑
        functionC(deferredObj, /*其他参数*/)
            .then((result: {a:string}) => {
                // 原done中的业务逻辑
            })
            .finally(() => {
                // 原always中的额外逻辑
            });
    }
}

private functionC(deferredObj: {promise: Promise<{a:string}>, resolve: (value: {a:string}) => void}, /*其他参数*/): Promise<{a:string}> {
    if(/*某个条件*/) {
        // 其他逻辑
        // 调用resolve函数触发Promise完成,完全对应原代码的d.resolve()
        deferredObj.resolve({ a: "completed" });
    }
    // 返回Promise供后续监听,对应原代码返回Deferred
    return deferredObj.promise;
}

关键说明

  1. 为什么不能用Promise.resolve():Promise.resolve()会创建一个全新的已完成Promise,无法改变数组中原有Promise的状态,和原代码中触发指定索引Deferred完成的逻辑完全不符。
  2. 复刻原逻辑的核心:通过将resolve函数与Promise绑定并存入数组,实现了和jQuery Deferred一样的“外部手动触发状态变化”的能力,同时保留了原生Promise的特性。
  3. 兼容性:这种写法完全符合ES6+标准,无需依赖任何库,行为和原代码完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:55:16