等待的forEach返回值之前完成 - AngularJS返回值、forEach、AngularJS

2023-09-13 04:13:25 作者:好名都让狗取了

概述:我创建使用离子型框架和AngularJS的应用程序。该应用程序有2种形式,其中用户可以上传图片。在第一种形式,图片上传字段允许上传只有一个图像和第二形式图片上传领域允许上传多张图片。用户上传图片后,我展示preVIEW用户右下方的图像场。然后,用户点击保存,它调用Web服务(定义为工厂)将图像上传到网站。服务功能实现了$ Q,让表单提交,上传图片后,只能继续。这是工作的罚款。

问题:当上传多张图片,我打电话给另一个辅助功能控制器,它循环(的forEach)在文件中的数据,并调用文件保存功能为每个文件。但是在这个辅助函数的执行不等待foreach循环完成。这让我得到保存的文件的第一个文件的细节,而不是剩余保存文件的详细信息。

下面是code我使用的是上传文件:

  .controller('AppCtrl',函数($ Q){  //上传单个文件。  $ scope.fileUpload =功能(FILEDATA){    变种推迟= $ q.defer();    如果(angular.isUndefined(FILEDATA)|| angular.isUndefined(fileData.dataURL)){      deferred.resolve(没有新的上传找到。);    }    其他{      VAR FILEDATA = {        文件:{          文件:(fileData.dataURL).replace(/ ^数据:影像\\ / [A-ZA-Z] {3,4}; BASE64,+ /克,''),          文件名:fileData.file.name,        },      };      AuthServiceContent.uploadNewFile(FILEDATA)。然后(功能(响应){        deferred.resolve(响应);      },函数(响应){        deferred.reject(响应);      });    }    返回deferred.promise;  };  //上传多个文件。  $ scope.fileUploadMultiple =功能(数据){    变种推迟= $ q.defer();    变种fileUploadStatus = [];    如果(angular.isUndefined(数据)|| angular.isUndefined(数据[0])){      deferred.reject(没有新的上传找到。);    }    其他{      angular.forEach(数据,功能(FILEDATA,指数){        $ scope.fileUpload(FILEDATA)。然后(功能(响应){          fileUploadStatus [指数] =响应;        },函数(响应){        });      });    }    回报(!?angular.isUndefined(fileUploadStatus)deferred.resolve(fileUploadStatus):deferred.reject(fileUploadStatus));  };  $ scope.createContent =功能(FORMDATA){    $ scope.fileUploadMultiple(formData.image)。然后(功能(响应){      如果(angular.isObject(响应)){        angular.forEach(响应函数(FILEDATA,指数){          的console.log(FILEDATA);          formData.image.und = {['FID':fileData.fid}];        });        的console.log(FORMDATA);      }      其他{      }    },功能(错误){      的console.log(更新失败!);    });    返回;  };}).factory('AuthServiceContent',函数($ Q $ HTTP,默认值){  VAR service_content = {    uploadNewFile:功能(FILEDATA){      变种推迟= $ q.defer();      $ http.post(DEFAULT.serviceURL +'文件',JSON.stringify(FILEDATA){        标题:{          内容类型:应用/ JSON,          '曲奇':'cookieData',        }      })      .success(功能(数据,状态,头,配置){        deferred.resolve(数据);      })      .error(功能(数据,状态,头,配置){        deferred.reject(数据);      });      返回deferred.promise;    }  };  返回service_content;}); 

我一直想这个超过2天,发现类似的问题,但它不工作。

更新:我通过添加循环额外的检查得到了这个工作,在这里进行更新功能的控制器上载多张图像。

  $ scope.fileUploadMultiple =功能(数据){    变种推迟= $ q.defer();    变种fileUploadStatus = [];    如果(angular.isUndefined(数据)|| angular.isUndefined(数据[0])){      deferred.reject(没有新的上传找到。);    }    其他{      VAR DATALENGTH =(data.length  -  1);      angular.forEach(数据,功能(FILEDATA,指数){        $ scope.fileUpload(FILEDATA)。然后(功能(响应){          fileUploadStatus [指数] =响应;          //检查是否我们在最后一个元素。如果是,则返回状态          //返回最后一个元素的递延状态。          如果(DATALENGTH ==指数){            deferred.resolve(fileUploadStatus);          }        },函数(响应){          //检查是否我们在最后一个元素。如果是,则返回状态          //返回最后一个元素的递延状态。          如果(DATALENGTH ==指数){            deferred.reject(fileUploadStatus);          }        });      });    }    返回deferred.promise;  }; 
AngularJS学习之前台搭建

解决方案

在回答更新code不工作。如果最后一个文件是最小的,它触发的决心的它上传后立即生效。我用,而不是fileIsUplaoded计数器。

  $ scope.fileUploadMultiple =功能(数据){    变种推迟= $ q.defer();    变种fileUploadStatus = [];    如果(angular.isUndefined(数据)|| angular.isUndefined(数据[0])){      deferred.reject(没有新的上传找到。);    }    其他{      VAR uploadCount = data.length;      angular.forEach(数据,功能(FILEDATA,指数){        $ scope.fileUpload(FILEDATA)。然后(功能(响应){          //如果一个文件被上传1降低uploadCount          uploadCount  - ;          fileUploadStatus [指数] =响应;          //检查是否我们在最后一个元素。如果是,则返回状态          //返回最后一个元素的递延状态。          如果(uploadCount == 0){            deferred.resolve(fileUploadStatus);          }        },函数(响应){          //如果一个文件没有上传1降低uploadCount          uploadCount  - ;          //检查是否我们在最后一个元素。如果是,则返回状态          //返回最后一个元素的递延状态。          如果(uploadCount == 0){            deferred.reject(fileUploadStatus);          }        });      });    }    返回deferred.promise;  }; 

Overview: I'm creating an app using ionic framework and AngularJS. The App has 2 forms where user can upload images. In first form, image upload field allows to upload only one image and second form image upload field allows to upload more than one images. After user uploads images I'm showing preview to user right below image field. Then user click on "Save", which calls Web Service (defined into factory) to upload images to site. The Service function implements $q, so that form submission can continue only after uploading images. This is working fine.

Problem: When uploading multiple images, I'm calling another helper function in controller which loop (forEach) over file data and call file save function for each file. But the execution in this helper function doesn't wait for forEach loop to complete. This is allowing me to get first file details of file saved, but not remaining saved files details.

Here is code I'm using for uploading file:

.controller('AppCtrl', function($q) {
  // Upload single file.
  $scope.fileUpload = function(fileData) {
    var deferred = $q.defer();
    if (angular.isUndefined(fileData) || angular.isUndefined(fileData.dataURL)) {
      deferred.resolve("No new upload found.");
    }
    else {
      var filedata = {
        "file" : {
          file: (fileData.dataURL).replace(/^data:image\/[A-Za-z]{3,4};base64,+/g, ''),
          filename: fileData.file.name,
        },
      };
      AuthServiceContent.uploadNewFile(filedata).then(function(response) {
        deferred.resolve(response);
      }, function(response) {
        deferred.reject(response);
      });
    }
    return deferred.promise;
  };

  // Upload multiple files.
  $scope.fileUploadMultiple = function(data) {
    var deferred = $q.defer();
    var fileUploadStatus = [];
    if (angular.isUndefined(data) || angular.isUndefined(data[0])) {
      deferred.reject("No new upload found.");
    }
    else {
      angular.forEach(data, function(fileData, index) {
        $scope.fileUpload(fileData).then(function(response) {
          fileUploadStatus[index] = response;
        }, function(response) {
        });
      });
    }

    return (!angular.isUndefined(fileUploadStatus) ? deferred.resolve(fileUploadStatus) : deferred.reject(fileUploadStatus));
  };

  $scope.createContent = function(formData) {
    $scope.fileUploadMultiple(formData.image).then(function(response) {
      if (angular.isObject(response)) {
        angular.forEach(response, function(fileData, index) {
          console.log(fileData);
          formData.image.und = [{'fid' : fileData.fid}];
        });
        console.log(formData);
      }
      else {
      }
    }, function(err) {
      console.log("updates failed!!!");
    });
    return;
  };
})

.factory('AuthServiceContent', function($q, $http, DEFAULT) {
  var service_content = {
    uploadNewFile: function(fileData) {
      var deferred = $q.defer();
      $http.post(DEFAULT.serviceURL + 'file', JSON.stringify(fileData), {
        headers : {
          'Content-Type': 'application/json',
          'Cookie': 'cookieData',
        }
      })
      .success(function (data, status, headers, config) {
        deferred.resolve(data);
      })
      .error(function (data, status, headers, config) {
        deferred.reject(data);
      });
      return deferred.promise;
    }
  };

  return service_content;
});

I've been trying this for more than 2 days and find similar issue, but its not working.

Updates: I got this working by adding extra check in loop, here is updated function in controller to upload multiple images.

  $scope.fileUploadMultiple = function(data) {
    var deferred = $q.defer();
    var fileUploadStatus = [];
    if (angular.isUndefined(data) || angular.isUndefined(data[0])) {
      deferred.reject("No new upload found.");
    }
    else {
      var dataLength = (data.length - 1);

      angular.forEach(data, function(fileData, index) {
        $scope.fileUpload(fileData).then(function(response) {
          fileUploadStatus[index] = response;
          // Check if we are at last element. If yes, then return status
          // Return deffered status on last element.
          if (dataLength == index) {
            deferred.resolve(fileUploadStatus);
          }
        }, function(response) {
          // Check if we are at last element. If yes, then return status
          // Return deffered status on last element.
          if (dataLength == index) {
            deferred.reject(fileUploadStatus);
          }
        });
      });
    }

    return deferred.promise;
  };

解决方案

The updated code in the answer is not working. If the last file is the smallest, it fires the resolve immediately after it's been uploaded. I use instead a fileIsUplaoded counter.

  $scope.fileUploadMultiple = function(data) {
    var deferred = $q.defer();
    var fileUploadStatus = [];
    if (angular.isUndefined(data) || angular.isUndefined(data[0])) {
      deferred.reject("No new upload found.");
    }
    else {
      var uploadCount = data.length;

      angular.forEach(data, function(fileData, index) {
        $scope.fileUpload(fileData).then(function(response) {
          // if a file is uploaded reduce the uploadCount by 1
          uploadCount --;
          fileUploadStatus[index] = response;
          // Check if we are at last element. If yes, then return status
          // Return deffered status on last element.
          if (uploadCount == 0) {
            deferred.resolve(fileUploadStatus);
          }
        }, function(response) {
          // if a file is not uploaded reduce the uploadCount by 1
          uploadCount --;
          // Check if we are at last element. If yes, then return status
          // Return deffered status on last element.
          if (uploadCount == 0) {
            deferred.reject(fileUploadStatus);
          }
        });
      });
    }

    return deferred.promise;
  };