如何使用$ q完成一个函数的执行,直到另外两个函数完成?

Sam*_*tar 3 javascript angularjs

我正在使用$ q的AngularJS实现.

鉴于以下功能:

   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;
   },
Run Code Online (Sandbox Code Playgroud)

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

os.doTask1()
    .then(function () {
        doTask3();
});
Run Code Online (Sandbox Code Playgroud)

我想同时开始doTask1和doTask2.有没有办法可以做到这一点,仍然延迟执行,以便doTask3()不会执行,直到doTask1和doTask2成功结束.

Mic*_*ley 6

$q.all是你在找什么.(文件)

$q.all在数组或对象中接受多个promise,并返回一个全新的promise,当所有传入的promise都被解析时,它将被解析.如果传入了一个promises数组,新的promise将通过一组与promise相对应的值来解决:

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

如果传入了一个key-promise对的对象,它将使用一个对象来解析,该对象的键与你传入的对象相匹配,每个值都很好地对应于该键的已解析promise的值:

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

由于承诺链(例如,当你从then函数返回一个promise时,它会创建一个新的promise,解析为你返回的promise的已解析值),你可以做一些很酷的事情:

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) { ... });
Run Code Online (Sandbox Code Playgroud)

如果任何传递的承诺$q.all被拒绝,那么返回的承诺也将被拒绝,这一点毫无价值.有关更多信息,请参阅Angular $q文档.


这与问题(几乎没有)相关,但我认为这是一个巧妙的伎俩:如果你碰巧使用CoffeeScript,你可以使用解构来获得promises的已解决值.

对于数组:

$q.all([doTask1(), doTask2()]).then ([result1, result2]) ->
  # ...
Run Code Online (Sandbox Code Playgroud)

对于对象

$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`
Run Code Online (Sandbox Code Playgroud)