返回按顺序处理的 Promise

4

我遇到了一个问题,使用 $q#all 方法返回 promises。

我希望使这些 promises 相互依赖,即:

如果我设置了 obj1、obj2 和 obj3,我希望以相同的顺序获取它们。

我该如何实现呢?

工厂:

mainFactory.$inject = ['$http', '$q'];

function mainFactory($http, $q) {
  var mainFactory = {
    getPromises: getPromises
  };

  return mainFactory;

  function getPromises(id) {
    promises = {
      'obj1': $http.get('http1'),
      'obj2': $http.get('http2'),
      'obj3': $http.get('http3'),
      'obj4': $http.get('http4', { params: { 'id': id } }),
      'obj5': $http.get('http5'),
      'obj6': $http.get('http6', { params: { 'id': id } })
    };

    return $q.all(promises);
  }
}

控制器:

MainCtrl.$inject = ['mainFactory'];

function MainCtrl(mainFactory) {
  var vm = this;
  mainFactory.getPromises(id)
    .then(getResponse)
    .catch(getError);

  function getResponse(response) {
    var keys = Object.keys(response), i = keys.length;
    while (i--) {
      var key = keys[i];
      console.log(key); // I want all the keys in order, i.e. => obj1, obj2.. and so on
      var value = response[key].data;
      switch(key) {
        ...
      }
    }
  }

  function getError(error) {
    console.log(error);
  }
}

编辑:

我也尝试了这种方法:

var promises = {};
return $http.get('/admin/http1.json').then(function (value) {
    promises['obj1'] = value;
  })
.then(function (result) {
    return $http.get('/admin/http2.json').then(function (value) {
    promises['obj2'] = value;
  });
}).then(function (result) {
    return $http.get('/admin/http3.json').then(function (value) {
    promises['obj3'] = value;
  });
});     
return $q.all(promises);

1
我不太擅长使用 Promises,抱歉。但是一个替代方案是使用 http://caolan.github.io/async/docs.html#.eachOfSeries - Plato
6
对象键(Object keys)本质上是无序的。请使用数组(Array)代替。 - Jared Smith
请查看关于 $q.serial() 的这篇文章,我觉得它会正好符合你的需求。http://www.codeducky.org/q-serial/ - mhodges
从代码中不清楚为什么这些承诺是“相互依赖的”。这可能会影响它们应该被处理的方式。 - Estus Flask
我使用了一个数组而不是对象,现在它可以工作了。感谢@JaredSmith。 - developer033
1
不客气。很高兴你解决了它。 - Jared Smith
2个回答

1

编辑2

错误,我刚才复制了你上面的代码,没有意识到它是一个对象。哈哈。

promises = [
  $http.get('http1'),
  $http.get('http2'),
  $http.get('http3'),
  $http.get('http4', { params: { 'id': id } }),
  $http.get('http5'),
  $http.get('http6', { params: { 'id': id } })
]

编辑 1

抱歉,我没有注意到评论中Jared Smith是正确的。

对象键本质上是无序的。使用数组代替。

编辑 0

对象键不会被排序。在声明您的承诺时请使用数组。

promises = [
  $http.get('http1'),
  $http.get('http2'),
  $http.get('http3'),
  $http.get('http4', { params: { 'id': id } }),
  $http.get('http5'),
  $http.get('http6', { params: { 'id': id } })
]

$q.all(promises)
  .then(functions(resolves){
      // resolves here is an array
  }).catch(function(err){ 
      // throw err 
  });

未捕获的语法错误:意外的标记:。不确定是否应该是一个对象...但它绝对不是有效的JavaScript。 - Patrick Roberts

1
使用$q.all将会按照没有特定的顺序解决每个承诺。如果你想在每个承诺被解决后执行它们,请使用承诺链式调用
function getPromises(id) {
  var getObjA = function () {
    return $http.get('http1');
  };

  var getObjB = function () {
    return $http.get('http2');
  };

  var getObjC = function () {
    return $http.get('http3');
  };

  var getObjD = function () {
    return $http.get('http4', { params: { 'id': id } });
  };

  var getObjE = function () {
    return $http.get('http5');
  };

  var getObjF = function () {
    return $http.get('http5', { params: { 'id': id } });
  };

  return getObjA()
    .then(getObjB)
    .then(getObjC)
    .then(getObjD)
    .then(getObjE)
    .then(getObjF);
}

编辑:作为额外信息,您可以在此处放置捕获语句来捕获这些Promise中的任何错误。
getPromises("id")
   .then(<success callback here>)
   .catch(<error callback that will catch error on any of the promises>);

意思是,一旦一个 Promise 失败,所有在它下面的后续 Promises 都不会被执行,并且会被 catch 语句捕获。

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