2016-03-08 47 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