使用 $timeout 时的 Promise 链接

Promise chaining when using $timeout

我正在尝试理解承诺 API 和链接,尤其是 $timeout.then() 一起使用时的时机。我从以下内容中期望的是,由于 $timeout returns 一个承诺,.then() 在它解决之前不会被调用。

但不是 ABAB,而是一直是 ABBA。

我如何使用 promise API 来确保在 .then() 获取之前真正完成长时间的 运行 调用(或使用 $timeout 的延迟调用)执行了吗?

代码

angular
  .module('app', [])
  .controller('ThenCtrl', ThenCtrl);

function ThenCtrl($timeout, $q) {
  var vm = this;

  vm.items = [];

  $q.when(pushA()).then(pushB());

  $timeout(pushA, 5000).then(pushB());

  function pushA() {
    vm.items.push('A');
  }

  function pushB() {
    vm.items.push('B');
  }
}

标记

<div ng-app="app">
  <div ng-controller="ThenCtrl as vm">
    {{vm.items}}
  </div>
</div>

我设置了一个fiddle:https://jsfiddle.net/kan3c61t/

给你。 我所做的实际上是在代码的 then 部分添加了一个 success 函数。

$timeout(pushA, 5000).then(function(success) {
    pushB()
  });

这是工作 demo

您也可以像这样添加 error function

 $timeout(pushA, 5000).then(function(success) {
    pushB()
  },function(error){console.log("Error");});

在搜索这个答案时,我也遇到了这个非常helpful link

不要调用 .then 方法中的函数。

  ̶$̶q̶.̶w̶h̶e̶n̶(̶p̶u̶s̶h̶A̶(̶)̶)̶.̶t̶h̶e̶n̶(̶p̶u̶s̶h̶B̶(̶)̶)̶;̶
  $q.when(pushA()).then(pushB);

  ̶$̶t̶i̶m̶e̶o̶u̶t̶(̶p̶u̶s̶h̶A̶,̶ ̶5̶0̶0̶0̶)̶.̶t̶h̶e̶n̶(̶p̶u̶s̶h̶B̶(̶)̶)̶;̶    
  $timeout(pushA, 5000).then(pushB);

而是将函数作为参数传递给 .then 方法。 $q 服务将保存这些函数以供稍后调用。

$q 服务的工作方式是将 .then 方法的参数存储为稍后调用的函数。在这种情况下,$q 服务正在存储 pushB() 返回的值,副作用是将 B 立即推入数组。

DEMO on JSFiddle

正如其他人所提到的 - 你更大的问题是你 .then(promise) 而不是 .then(function)

承诺代表价值+时间。这是已经开始的操作的结果。承诺是一个值 - then 等待 函数 。你不能 "run a promise after another promise" - 因为承诺意味着操作已经开始。

当您 then(x) 函数 以外的任何东西时,它会被忽略。在 promises 规范中这是一个不幸的选择,但我们必须接受它。

由于您的调用是同步的,因此您不应为此使用承诺。如果您的代码执行同步操作,您可以使用 ; 而不是 then:

对操作进行排序
pushA();
pushB(); 

如果这是一个 returns 承诺的调用,那么它将变成:

pushA().then(pushB);

调用 $q.when 将非承诺转换为承诺是没有意义的。

我会写成:

pushA();
$timeout(5000).then(pushB); 

将第一个同步操作转换为承诺返回函数或在超时以外的任何地方涉及承诺是没有意义的。如果你需要 pushA 在 5000ms 之后发生,我仍然可能会写:

$timeout(5000).then(pushA).then(pushB)

因为我认为它更具可读性,而且我们不直接涉及 pushApushB 承诺。