【问题标题】:Angularjs asynchronous calls in a loop循环中的Angularjs异步调用
【发布时间】:2016-04-29 19:21:35
【问题描述】:

以下是我在项目中使用的代码,允许用户上传文件。 对于每个选定的文件,“$scope.upload”函数都会被异步调用。

因为这些是异步调用,所以每次调用不依赖于之前的调用。

但我的要求是只有在成功回调函数执行后, 那么下一次上传应该发生,因为每次上传都取决于值 由上一次上传返回。

请告诉我如何实现。 注意:$scope.upload 是部分 Angular 文件上传 js (https://github.com/danialfarid/ng-file-upload)

$scope.startUploading = function ($files, errFiles, item) {           

        //$files: an array of files selected
        for (var idx = 0; idx < $files.length; idx++) {
            var $file = $files[idx];


            (function (index) {
                $scope.upload[index] = $upload.upload({
                    url: "../UploadCommentAttachment",
                    method: "POST",
                    file: $file, 
                    data: item 
                }).success(function (responseData, status, headers, config) {

                       item.AuditCommentAttachments.push(responseData);
                       item.CommentId = responseData.CommentId;
                       item.AuditId = responseData.AuditId;
                       item.Operation = "EDIT";
                       item.CommentAttachmentID = responseData.CommentAttachmentID;
                    }

                });
            })(idx);

        }  ///-- for loop end         
    } // startuploading end

【问题讨论】:

  • here 提供的解决方案很优雅,适合我。

标签: javascript angularjs asynchronous


【解决方案1】:

我已经修改了 ng-file-upload 中的一个小提琴,以逐个处理帖子,并使用上一篇帖子对当前帖子的响应。请查看my fiddle

这是 javascript 代码的一部分

function sequentialFileUploadWithReduce(values) {
    var result = ''
    var dfd = $q.defer();

    dfd.resolve();
    return values.reduce(function(currentValue, nextValue, index, values) {
      return Upload.upload({
        url: "https://angular-file-upload-cors-srv.appspot.com/upload",
        method: "POST",
        data: currentValue
      }).then(function(resp) {
        // file is uploaded successfully
        //debugger;
        result += "Uploading file " + index++;
        console.log("Uploading file " + index);
        nextValue.item = resp;
      }, function(resp) {
        // handle error
      }, function(evt) {
        // progress notify
      });
    }, dfd.promise).then(function(responce) {

      return result;
    });
  }

希望这会有所帮助。另请查看控制台和网络选项卡以验证解决方案是否正常工作。

【讨论】:

    【解决方案2】:

    通用答案

    顺序执行异步操作的方法是使用由.then 方法派生的promise 链接它们。后续承诺使用的值应在.then 方法中返回

    function sequentiallyExecute = function (opList) {
        //create initial object
        var passedObject = {};
        passedObject.dataList = [];
        passedObject.response = {};
    
        //create initial promise
        var promise = $q.when(passedObject);
    
        //sequentially execute opList
        angular.forEach(opList, function(op) {
            promise.then(function (passedObject) {
                var iPromise = asyncOperation(op, passedObject);
                iPromise.then(function onFulfulled(response) {
                    //save response for chaining
                    passedObject.response = response;
                    //push data to list
                    passedObject.dataList.push(response.data);
                    //return object for chaining
                    return passedObject;
                });
                //return promise for chaining
                return iPromise;
            });
        });
    
        //return promise to client
        return promise;
    };
    

    在客户端代码中,检索最终数据。

    (sequentiallyExecute(opList)
    ).then (function onFulfilled(passedObject) {
        $scope.dataList = passedObject.dataList;
    }).catch (function onRejected(error) {
        console.error(error);
    });
    

    有关链接的更多信息,请参阅AngularJS $q Service API Reference -- chaining promises


    具体答案

    不要使用.success 方法(不可链接),而是使用.then 方法(可链接的)。

    function asychOperation(op, passedObject) {
        var $file = op.$file
        var item = passedObject.item;
    
        var httpPromise = $upload.upload({
             url: "../UploadCommentAttachment",
                        method: "POST",
                        file: $file, 
                        data: item 
        });
    
        var derivedPromise = httpPromise.then(function (response) {
            var data = response.data
            passedObject.dataList.push(data);
            var newItem = {};
            newItem.CommentId = data.CommentId;
            newItem.AuditId = data.AuditId;
            newItem.Operation = "EDIT";
            newItem.CommentAttachmentID = data.CommentAttachmentID;
            passedObject.item = newItem;
        });
    
        var promise = derivedPromise.then (function onFulfilled() {
            //return object for chaining
            return passedObject;
        });
    
        //return promise for chaining
        return promise;
    };
    

    $http 服务的 .success.error 方法已从 AngularJS 框架中删除。请改用.then.catch 方法。

    有关详细信息,请参阅

    结论

    因为调用 Promise 的 .then 方法会返回一个新的派生 Promise,所以很容易创建一个 Promise 链。

    可以创建任意长度的链,并且由于可以使用另一个 Promise 来解决 Promise(这将进一步推迟其解决方案),因此可以在链中的任何点暂停/延迟解决 Promise。这使得实现强大的 API 成为可能。1

    【讨论】:

      【解决方案3】:

      下面的代码为我完成了所需的工作,顺序执行异步操作,没有链接。

         $scope.startUploading = function ($files, item) 
          {
            var cntr = 0;
            function next() 
            {
                if (cntr < $files.length) 
                {
      
                $scope.upload[cntr] = $upload.upload({
                                      url: "../UploadCommentAttachment",
                                      method: "POST",
                                      file: $files[cntr],
                                      data: item
                                  }).then(function (responseData) {                                item.AuditCommentAttachments.push(responseData.data);
                                  item.CommentId = responseData.data.CommentId;
                                  item.AuditId = responseData.data.AuditId;
                                  item.Operation = "EDIT";
                                  item.CommentAttachmentID = responseData.data.CommentAttachmentID;
                                  cntr++;
                                  next();
                              });                    
            }
        }
        next();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-07-03
        • 2017-06-16
        • 1970-01-01
        • 1970-01-01
        • 2018-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多