简体   繁体   English

JavaScript:如何在for循环中从Asyn函数返回值

[英]JavaScript: how to return a value from a asyn function in a for loop

I got a Service as follows to return back a value: 我得到了一个服务,如下所示返回一个值:

// Service.js
var done = false;
var readyToSubmit = function(answerArr, len) {
  var threshold = 0;
  for (var i = 0; i < answerArr.length; i++) {
    var id = answerArr[i].focus + '_' + userData.uid;
    appStore.getDoc(id).then(function(doc) {
      if (doc.doneRate == 100) {
        threshold++;
        if (threshold == len) {
          done = true;
        } else {
          done = false;
        }
      }
    });
  }
  return done; // here, It always returns 'undefined'.
};

I would like to use this service in my AngularJs project, like below: 我想在我的AngularJs项目中使用此服务,如下所示:

var answerArr = $scope.homework.items;
var len = answerArr.length;
$scope.$on('appChange', function(e, doc) {
  $scope.done = hwService.readyToSubmit(answerArr, len);
});

However, always without luck, although I tried call readyToSubmit(para1, para2, callback) , this kind of calling doesn't make any fortune. 但是,总是没有运气,尽管我尝试调用readyToSubmit(para1, para2, callback) ,但这种调用不会带来任何readyToSubmit(para1, para2, callback) It really bugs me for about 4 hours. 这真的使我烦了大约4个小时。 So anyone would like to do me a favor here? 所以有人想在这里帮我一个忙吗? Many many thanks~~ :) 非常感谢~~ :)

You can't use async functions like this. 您不能使用这样的异步函数。

You can use angulars promise to achieve this. 您可以使用角度承诺来实现这一目标。

// Service.js
var done = false;
var defered = $q.defer() //include in service function $q
var readyToSubmit = function(answerArr, len) {
  var threshold = 0;
  for (var i = 0; i < answerArr.length; i++) {
    var id = answerArr[i].focus + '_' + userData.uid;
    appStore.getDoc(id).then(function(doc) {
      if (doc.doneRate == 100) {
        threshold++;
        if (threshold == len) {
          defered.resolve(true);
        } else {
          done = false;
        }           
      }
    });
  }
  return done; // here, It always returns 'undefined'.
};

Use a defer object to make use of the angular promise. 使用延迟对象来利用角度承诺。 if defered.resolve() is called, it will invoke the .then . 如果defered.resolve() ,它将调用.then

var answerArr = $scope.homework.items;
var len = answerArr.length;
$scope.$on('appChange', function(e, doc) {
  hwService.readyToSubmit(answerArr, len).then(function(done){
    $scope.done = done;
  });
});

The point is you can not return the done variable because when you want to return it, the callback function in your for loop: 关键是您不能返回done变量,因为当您想返回它时,您的for循环中的回调函数:

appStore.getDoc(id).then(function(doc) {
    //...
})

hasn't got called yet. 还未接到电话。 since as you also mentioned in your question it is a asynchronous function . 因为正如您在问题中也提到的那样,它是一个asynchronous function

You have 2 options, first is using Angular promises which is described in another answer, but you also have one other solution which is using a callback in readyToSubmit function: 您有2个选项,首先是使用Angular Promise,这在另一个答案中有描述,但是您还有另一个解决方案,其在readyToSubmit函数中使用回调:

var done = false;
var readyToSubmit = function(answerArr, len, callback) {
  var threshold = 0;
  for (var i = 0; i < answerArr.length; i++) {
    var id = answerArr[i].focus + '_' + userData.uid;
    appStore.getDoc(id).then(function(doc) {
      if (doc.doneRate == 100) {
        threshold++;
        if (threshold == len) {
          callback(true);
        } else {
          callback(false);
        }
      }
    });
  }
  //no need to return anything
  //return done;
};

then to use in your angular scope: 然后在您的角度范围内使用:

var answerArr = $scope.homework.items;
var len = answerArr.length;
$scope.$on('appChange', function(e, doc) {
  hwService.readyToSubmit(answerArr, len, function(done){
      $scope.done = done;
  });
});

this way, the point that you have to consider is, this line of code: 这样,您必须要考虑的是这一行代码:

$scope.done = done;

would get called more than once. 将不止一次地被致电。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM