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

如何将jQuery Deferred替换为原生Promise?替换后Promise.all未触发

问题解决:原生Promise替换jQuery Deferred后Promise.all不触发回调

问题场景

按钮点击触发的handleClick函数中,原本使用jQuery Deferred时Promise.all能正常执行并输出show this,但将其中的Deferred替换为原生Promise后,Promise.all的后续回调不再触发。

原错误处理的jQuery Deferred片段:

return new $.Deferred()
  .resolve({
    folderError: error,
  })
  .promise();

替换后的原生Promise写法:

return new Promise((resolve)=>{
  resolve({
    folderError: error,
  })
})

问题原因

核心矛盾是jQuery Deferred对象与原生Promise的兼容性问题:api.cloneFolder(ad.id)返回的是jQuery Deferred对象,当在它的.then()回调中返回原生Promise时,jQuery的Deferred链无法正确识别并转换这个原生Promise的状态,导致Promise.all无法感知该异步操作已完成,最终卡住不触发后续回调。

另外,代码的default分支未返回任何值,会导致clonePromises数组中混入undefined,虽然原生Promise.all会将undefined视为已resolved,但混合jQuery Deferred后会加剧状态识别的混乱。

解决方案

  • 方案1:将jQuery Deferred转换为原生Promise
    在调用api.cloneFolder时用Promise.resolve()包裹,把jQuery的Deferred对象转换为原生Promise,确保整个异步链统一为原生Promise标准:

    case 'folder':
      return Promise.resolve(api.cloneFolder(ad.id)).catch((err) => {
        let error = 'Unknown error';
        try {
          error = JSON.parse(err.responseText)?.message || JSON.parse(err.responseText)?.errors?.message;
        } catch {
          // 忽略解析错误
        }
        return { folderError: error };
      });
    

    这里用.catch()替代原有的.then(null, errHandler),无需手动创建新Promise,.catch的返回值会自动作为resolved结果传入下一个链。

  • 方案2:统一所有异步操作为原生Promise
    如果其他克隆方法(cloneA/cloneB等)也返回jQuery Deferred,全部用Promise.resolve()包裹,同时给default分支返回一个已resolved的Promise,避免数组中出现undefined:

    const clonePromises = cloneServices?.getAds().map((ad: IAds) => {
      switch(ad.type) {
        case 'tree':
          return Promise.resolve(api.cloneA(ad.id));
        case 'creativegroup':
          return Promise.resolve(api.cloneB(ad.id));
        case 'creative':
          return Promise.resolve(api.cloneC(ad.name, ad.id, ad.hasVariations));
        case 'trackerresource':
          return Promise.resolve(cloneTracker(ad));
        case 'folder':
          return Promise.resolve(api.cloneFolder(ad.id)).catch((err) => {
            let error = 'Unknown error';
            try {
              error = JSON.parse(err.responseText)?.message || JSON.parse(err.responseText)?.errors?.message;
            } catch {
              // noop
            }
            return { folderError: error };
          });
        default:
          // 无法克隆时返回标记值
          return Promise.resolve(null);
      }
    });
    
  • 方案3:简化错误处理逻辑
    无需手动创建Promise,直接在错误回调中返回错误对象即可——无论是jQuery Deferred还是原生Promise,.catch(或.then的错误回调)都会自动将返回值包装为resolved状态:

    case 'folder':
      return api.cloneFolder(ad.id).then(null, (err) => {
        let error = 'Unknown error';
        try {
          error = JSON.parse(err.responseText)?.message || JSON.parse(err.responseText)?.errors?.message;
        } catch {
          // noop
        }
        return { folderError: error };
      });
    

    若已将整个链转为原生Promise,该写法同样适用。

验证修改

采用任一方案修改后,Promise.all会正确等待所有异步操作完成,触发后续.then回调并输出show this。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 18:30:54