如何在使用$q时延迟执行函数直到其他两个函数完成?

3
我将使用AngularJS中的$q实现进行翻译。
给定以下函数:
   doTask1: function ($scope) {
       var defer = $q.defer();
       $http.get('/abc')
           .success(function (data) {
               defer.resolve();
           })
           .error(function () {
               defer.reject();
           });
       return defer.promise;
   },

   doTask2: function ($scope) {
       var defer = $q.defer();
       var x = 99;
       return defer.promise;
   },

我知道可以像这样延迟执行另一个函数:

os.doTask1()
    .then(function () {
        doTask3();
});

我希望能同时启动doTask1和doTask2。有没有一种方法可以做到这一点,同时延迟执行,以便在doTask1和doTask2成功结束之前不执行doTask3()。


我对JS一无所知,但我认为你要找的术语叫做回调函数。谷歌搜索JavaScript回调似乎给出了许多有希望的结果,但由于我在JS方面没有经验,所以无法保证它们的准确性。 - TheOneWhoPrograms
1个回答

6

$q.all 是你要寻找的内容。(文档)

$q.all 接受多个承诺,可以是数组或对象,并返回一个全新的承诺,当所有传入的承诺都得到解决时,该承诺将被解决。如果您传入一组承诺,则新承诺将以与承诺对应的值数组解决:

$q.all([doTask1(), doTask2()]).then(function(results) {
  // results[0] == result of doTask1
  // results[1] == result of doTask2
  doTask3();
});

如果您传入一个键-值对的对象,它将被解析为一个具有与您传入对象相匹配的键的对象,并且每个值都很好地对应于该键的已解决承诺的值:

$q.all({one: doTask1(), two: doTask2()}).then(function(results) {
  // results.one == result of doTask1
  // results.two == result of doTask1
  doTask3();
});

由于承诺链接(例如,当您从then函数返回承诺时,它会创建一个新的承诺,该承诺解析为您返回的承诺的解析值),您可以做一些很酷的事情:
var bothPromises = $q.all([doTask1(), doTask2()]);

var task3Promise = bothPromises.then(function(results) {
  var result1 = results[0];
  var result2 = results[1];
  return doTask3(result1, result2);
});

task3Promise.then(function(resultOfDoTask3) { ... });

值得注意的是,如果传递给$q.all的承诺中有任何一个被拒绝,那么返回的承诺也将被拒绝。有关更多信息,请参见Angular $q文档
这与问题(稍微)有些不相关,但我认为这是一个很棒的技巧:如果你恰好使用CoffeeScript,你可以使用解构来获取promise的resolved值。
对于数组:
$q.all([doTask1(), doTask2()]).then ([result1, result2]) ->
  # ...

对于对象

$q.all(one: doTask1(), two: doTask2()).then ({one, two}) ->
  # note that you have to use the same key names
  # as in the object you passed to `$q.all`

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接