Angularjs承诺不在控制器

时间:2017-04-27 02:33:26

标签: javascript angularjs cordova promise angular-promise

我有一个使用angular和cordova的离子(v1)项目。 我循环遍历一组文件名,并将每个文件数据附加到FormData对象中,该对象必须上传到服务器。

为了读取文件数据,Cordova/HTML5提供了一些异步的方法。我正在使用angular的$q承诺来调用这些方法。

然后我想使用$q.all等待所有承诺解决并开始上传。

但是承诺永远不会得到解决,$q.all(promises).then中解析的功能块永远不会被调用。

奇怪的是,如果我拒绝承诺而不是使用deferred.reject解析承诺,则会调用$q.all的错误方法。

我如何解决承诺?

以下是代码:

//Inside a controller
var promises = [];

for (var key in $scope.rArray) {
      if ($scope.rArray.hasOwnProperty(key)) {
          var deferred = $q.defer();
          var tmpFile = $scope.rArray[key];

          var i  = cordova.file.externalRootDirectory + "/" + tmpFile;

          window.resolveLocalFileSystemURL(i, function(fileEntry) {
              fileEntry.file(function(file) {
                  var reader = new FileReader();
                  reader.onloadend = function(e) {
                      console.log('onloadend callled');
                      var fileBlob = new Blob([this.result], { type:file.type});
                      fd.append('file', fileBlob,file.name);
                      deferred.resolve(fd); //if reject here it is reflected
                      //$rootScope.$apply(). tried this too

                  };
                  reader.readAsArrayBuffer(file);

              }, function(e) {
                  console.log('error getting file', e);
                  deferred.reject(e);
              });
          }, function(e) {
              console.log('Error resolving fs url', e);
              deferred.reject(e);
          });

          promises.push(deferred.promise);
      }
    };

    $q.all(promises).then(function (dataAr) {
      console.log('promises resolved..'); //NEVER CALLED
      var request = new XMLHttpRequest();
      request.open('POST', ENV.baseUrl+"/st/st");
      request.send(fd);
    }, function errorfn(err) {
      console.error(JSON.stringify(err));
    })

1 个答案:

答案 0 :(得分:1)

问题是public class EditProfile extends AppCompatActivity { private TextView originTV; private EditText descriptionET; private ImageView cameraIV, mainIV; private Button doneButton; private static final String EDIT_PROFILE = "EDIT_PROFILE"; private UpdateUserString updateUserString; private int PLACE_AUTOCOMPLETE_REQUEST_CODE = 20; private User localActivityUser; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_16e_profile_edit); bindActivity(); } private void bindActivity() { localActivityUser = Global_Class.getInstance().getValue().user; originTV = (TextView) findViewById(R.id.editProfile_originTV); descriptionET = (EditText) findViewById(R.id.editProfile_descriptionET); cameraIV = (ImageView) findViewById(R.id.editProfile_cameraIV); mainIV = (ImageView) findViewById(R.id.editProfile_imageIV); doneButton = (Button) findViewById(R.id.editProfile_doneButton); doneButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(!localActivityUser.getDescription().equals(descriptionET.getText().toString())) { //Call api to update my backend. UpdateUserStringAsyncTask updateUserStringAsyncTask = new UpdateUserStringAsyncTask("description",descriptionET.getText().toString()); updateUserStringAsyncTask.execute(); } else if(!localActivityUser.getOrigin().equals(originTV.getText())) { //Call api to update my backend UpdateUserStringAsyncTask updateUserStringAsyncTask = new UpdateUserStringAsyncTask("origin",originTV.getText().toString()); updateUserStringAsyncTask.execute(); } } }); } 最后一个,当任何var deferred函数的任何回调被调用时

所以,只有一个承诺可以被解决或拒绝

使用Promise.all,一次拒绝就足以拒绝Promise.all返回的Promise - 但所有承诺必须解决Promise.all才能解决

我最初在你的代码中玩弄了一个闭包的想法 - 但是使用常见的JS方法似乎是一个更好的解决方案 - Object.keys和Array#map

resolveLocalFileSystemURL