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

AngularJS中forEach结合$q.all批量上传文件未等待全部完成问题

解决AngularJS批量上传SharePoint时$q.all提前完成的问题

看起来你的问题出在promises数组没有正确收集每个文件的异步上传任务,加上deferred对象没有在上传完成时正确调用resolve/reject,才导致$q.all误以为第一个文件完成就全部结束了。我帮你修正代码并拆解关键点:

问题根源分析

从你给出的代码片段看,至少有两个明显问题:

  • promises.push(deferred)被注释了,导致$q.all根本没收到后续文件的上传任务
  • 即使没注释,你push的是deferred对象而非它的promise属性,$q.all无法正确追踪异步状态
  • 缺少上传完成后对deferred的resolve/reject操作,promise永远处于pending状态

修正后的完整代码

factory.UploadFilesByBatch = function(arrayBuffer, folderName) {
  var promises = [];
  
  // 先统一获取SharePoint的FormDigest(避免每个文件重复请求)
  return factory.GetFormDigest().then(function(formDigestValue) {
    // 遍历所有待上传文件
    angular.forEach(arrayBuffer, function(item) {
      var deferred = $q.defer();
      // 把当前文件的上传promise加入追踪数组
      promises.push(deferred.promise);
      
      console.log(`开始上传文件: ${item.fileName}`);
      
      // 发起SharePoint文件上传请求
      $http({
        method: 'POST',
        url: `/_api/web/getfolderbyserverrelativeurl('${folderName}')/files/add(overwrite=true,url='${item.fileName}')`,
        headers: {
          'Accept': 'application/json;odata=verbose',
          'X-RequestDigest': formDigestValue,
          'Content-Type': item.fileType // 要匹配文件的MIME类型
        },
        data: item.arrayBuffer // 传入文件的ArrayBuffer数据
      }).then(function(response) {
        console.log(`文件 ${item.fileName} 上传成功`);
        // 上传成功,标记当前promise完成
        deferred.resolve(response.data);
      }).catch(function(error) {
        console.error(`文件 ${item.fileName} 上传失败`, error);
        // 上传失败,标记当前promise失败
        deferred.reject(error);
      });
    });
    
    // 等待所有上传任务完成
    return $q.all(promises);
  });
};

关键注意事项

  1. 统一获取FormDigest:SharePoint的FormDigest有效期足够处理批量上传,无需每个文件都请求一次,既提升效率又避免重复请求
  2. 正确收集promise:必须将deferred.promise加入数组,而非deferred对象本身——$q.all只能识别promise对象的状态
  3. 必须收尾promise:在$http的成功/失败回调里一定要调用deferred.resolve()或deferred.reject(),否则该promise会一直处于pending状态,$q.all永远不会触发完成
  4. 返回最终promise:整个函数返回$q.all的结果,这样调用方可以直接用then/catch处理全部上传完成或失败的逻辑

调用示例

// 假设你已经收集好文件的arrayBuffer、文件名、类型组成的数组
factory.UploadFilesByBatch(yourFileArray, 'Shared Documents/批量上传文件夹')
  .then(function(allUploadResults) {
    alert('所有文件上传完成!');
    console.log('每个文件的上传结果:', allUploadResults);
  })
  .catch(function(error) {
    alert('至少有一个文件上传失败,请检查日志');
    console.error('上传失败详情:', error);
  });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:20:19