2016-03-08 124 views
11

我在尝试了解承诺API和链接,特别是当$timeout.then()一起使用时的时间。我之前所期望的是,由于$timeout返回一个承诺,.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> 

我已经成立了一个小提琴:https://jsfiddle.net/kan3c61t/

回答

13

不要调用.then方法里面的功能。

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

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

相反传递函数作为参数向.then方法。 $q服务将保存稍后调用的函数。

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

DEMO on JSFiddle

+0

这也是一个非常有趣的解决方案。 –

+2

非常清楚地表明。这些括号可以产生什么不同。 – twip

+0

这非常帮助我 – Fergus

6

在这里你去。 我所做的基本上是在代码的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

+1

这是对底层API结构的极好提示;谢谢。 – twip

4

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

承诺代表价值+时间。这是已经开始的操作的结果。承诺是一个值 - then等待函数。你不能“在承诺之后履行承诺” - 因为承诺意味着操作已经开始。

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

由于你的呼叫是同步的,你不应该使用它的承诺。如果你的代码做了同步的,你可以序列与;和行动不then:如果它是返回的承诺那么它只是变成一个电话

pushA(); 
pushB(); 

pushA().then(pushB); 

有呼吁$q.when不点,这将非承诺转化为承诺。

我会写为:

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

没有指向第一个同步动作转换为一个承诺返回函数或承诺,除了超时任何地方参与。如果您需要pushA 5000毫秒发生后,本身我还是可能会写:

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

因为我认为这是更具可读性,并再次,我们不直接涉及pushApushB与承诺。

+0

谢谢你的回应。有时很难捕捉到意图,同时对SO帖子既简短又明确。我试图捕捉的是我们打算在B之前解决A的场景,而A是必须承担延迟的承诺。含义:我希望'pushA'完成它的工作,包括延迟,然后再执行'pushB'。这是一个更新的小提琴,通过您的输入实现,这帮助我达到了我所期待的目标:https://jsfiddle.net/nam3cbaw/1/ – twip