原生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; }
关键说明
- 为什么不能用
Promise.resolve():Promise.resolve()会创建一个全新的已完成Promise,无法改变数组中原有Promise的状态,和原代码中触发指定索引Deferred完成的逻辑完全不符。 - 复刻原逻辑的核心:通过将resolve函数与Promise绑定并存入数组,实现了和jQuery Deferred一样的“外部手动触发状态变化”的能力,同时保留了原生Promise的特性。
- 兼容性:这种写法完全符合ES6+标准,无需依赖任何库,行为和原代码完全一致。
内容的提问来源于stack exchange,提问作者Itsme
相关产品推荐
相关产品推荐

