使用$ timeout时保证链接

twi*_*wip 11 angularjs angular-promise

我正在尝试理解promise API和链接,特别$timeout是使用时的时间.then().我对以下内容的期望是,自从$timeout返回一个承诺后,.then()在它解决之前不会被调用.

但是ABAB不是ABAB,而是ABBA.

如何使用promise API确保在执行执行$timeout之前长时间运行的调用(或使用延迟调用)实际上已完成.then()

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

标记

<div ng-app="app">
  <div ng-controller="ThenCtrl as vm">
    {{vm.items}}
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

我设置了一个小提琴:https://jsfiddle.net/kan3c61t/

geo*_*awg 14

不要调用.then方法内的函数.

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

  $timeout(pushA, 5000).then(pushB);
  //$timeout(pushA, 5000).then(pushB());
Run Code Online (Sandbox Code Playgroud)

而是将函数作为参数传递给.then方法.该$q服务将保留稍后调用的那些函数.

的方式$q服务的工作原理是它存储的参数.then方法稍后调用的函数.在这种情况下,$q服务正在存储返回的值pushB(),其副作用是B立即推送到阵列上.

JSFiddle上DEMO

  • 非常清楚地说明.这些括号对可以有什么不同. (2认同)

Sat*_*j S 6

干得好.我所做的实际上是在代码部分添加了一个success函数then.

$timeout(pushA, 5000).then(function(success) {
    pushB()
  });
Run Code Online (Sandbox Code Playgroud)

这是工作演示.

你也可以添加error function这样的东西

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

在搜索这个答案时,我也遇到了这个非常有用的链接


Ben*_*aum 5

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

Promises 代表一个值 + 时间。这是一个已经开始的操作结果。promise 是一个值then等待函数。你不能“一个接一个的运行一个承诺”——因为一个承诺意味着操作已经开始。

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

由于您的调用是同步的,因此您不应使用 promise。如果您的代码执行同步操作,您可以使用;和 不 对操作进行排序then

pushA();
pushB(); 
Run Code Online (Sandbox Code Playgroud)

如果它是一个返回 promise 的调用,那么它就会变成:

pushA().then(pushB);
Run Code Online (Sandbox Code Playgroud)

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

我会把它写成:

pushA();
$timeout(5000).then(pushB); 
Run Code Online (Sandbox Code Playgroud)

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

$timeout(5000).then(pushA).then(pushB)
Run Code Online (Sandbox Code Playgroud)

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