JavaScript:如何从for循环中的异步函数返回值

时间:2014-03-15 15:16:28

标签: javascript asynchronous return-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'.
};

我想在我的AngularJs项目中使用此服务,如下所示:

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

然而,总是没有运气,虽然我试着打电话readyToSubmit(para1, para2, callback),但这种打电话并没有赚到任何财富。它真的让我困扰了大约4个小时。所以有人想帮我一个忙吗?非常感谢~~ :)

2 个答案:

答案 0 :(得分:0)

您无法使用此类异步功能。

您可以使用angulars承诺来实现这一目标。

// 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'.
};

使用延迟对象来使用角度承诺。 如果调用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;
  });
});

答案 1 :(得分:0)

关键是你无法返回done变量,因为当你想要返回它时,for循环中的回调函数:

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

还没有被召唤。因为你在问题中也提到它是asynchronous function

你有2个选项,首先是使用另一个答案中描述的Angular promises,但你还有另一个在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;
};

然后在角度范围内使用:

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

这样,您必须考虑的一点是,这行代码:

$scope.done = done;

会不止一次被召唤。