我正在尝试理解promise API和链接,尤其是$timeout
与.then()
一起使用的时间。我对以下内容的期望是,由于$timeout
返回一个承诺,.then()
在解决之前不会被调用。
但不是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');
}
}
标记
<div ng-app="app">
<div ng-controller="ThenCtrl as vm">
{{vm.items}}
</div>
</div>
我已经设置了一个小提琴:https://jsfiddle.net/kan3c61t/
答案 0 :(得分:14)
不要调用.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
推送到数组上。
答案 1 :(得分:6)
你走了。
我所做的实际上是在代码的success
部分添加了then
函数。
$timeout(pushA, 5000).then(function(success) {
pushB()
});
这是工作demo。
您也可以像这样添加error function
$timeout(pushA, 5000).then(function(success) {
pushB()
},function(error){console.log("Error");});
在搜索这个答案时,我也遇到了这个问题helpful link
答案 2 :(得分:4)
正如其他人所说 - 你的更大问题是你.then(promise)
而不是.then(function)
。
承诺代表价值+时间。它是已经开始运营的结果。承诺是一个值 - then
等待函数。你不能在另一个承诺之后履行承诺&#34; - 因为承诺意味着操作已经开始。
当then(x)
除函数以外的任何内容时,它将被忽略。这是承诺规范中的一个不幸的选择,但我们必须忍受它。
由于您的呼叫是同步的,因此您不应使用promises。如果您的代码执行了某些同步操作,则可以使用;
而非then
pushA();
pushB();
如果它是一个返回promises的调用,那么它就变成了:
pushA().then(pushB);
调用$q.when
将非承诺转换为承诺是没有意义的。
我把它写成:
pushA();
$timeout(5000).then(pushB);
没有必要将第一个同步动作转换为promise返回函数,或者除了超时之外的任何地方都包含promise。如果您需要在{5000}之后发生pushA
,我仍然可能会写:
$timeout(5000).then(pushA).then(pushB)
由于我认为它更具可读性,因此我们不会直接让pushA
和pushB
参与承诺。