2016-03-08 3 views
11

私は約束のAPIと連鎖、特にが.then()で使用されるタイミングを理解しようとしています。私が次のことから期待していたのは、が約束を返すので、解決されるまで.then()は呼び出されないということです。

しかし、ABABではなく、常にABBAです。

.then()が実行される前に、長期の呼び出し(または$timeoutを使用した遅延呼び出し)が実際に完了するように、promise APIを使用するにはどうすればよいですか?

コード

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

に出くわしました。

$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");}); 

を追加することができ、私はまた.thenメソッド内の機能を起動しないでください。この非常にhelpful link

+1

これは、基礎となるAPI構造の優れたリマインダーです。ありがとうございました。 – twip

4

他の人が述べたように - あなたの大きな問題があること、あなた.then(promise)ない.then(function)

約束は値+時間を表します。既に開始された操作の結果はです。約束は価値です - thenファンクションを待ちます。約束は、操作がすでに開始されていることを意味するため、「別の約束の後に約束を実行する」ことはできません。

以外の機能の場合は、は無視されます。これは約束のスペックでは不幸な選択ですが、私たちはそれと一緒に生活しなければなりません。

あなたの通話は同期的なので、約束をしてはいけません。あなたのコードは同期何かをした場合、あなたは;なくthenとアクションの配列を決定することができます

pushA(); 
pushB(); 

それは約束を返す呼び出しの場合、それだけで次のようになります。

pushA().then(pushB); 

$q.whenどれを呼び出すにはポイントがありません約束を約束に変換する。

私はそれを書くと思います:

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

約束を返す関数への最初の同期動作を変換したり、任意の場所にタイムアウトを除く約束が関与しても意味がありません。私はそれがより読みやすいと思いますので

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

と再び我々は直接約束とpushApushBを含まない:あなたは5000ms後に発生するpushAが必要な場合は、それ自体、私はおそらくまだ記述します。

+0

ありがとうございました。 SOの投稿のために簡潔で明瞭である一方で、意図をうまくとらえることは時には非常に困難です。私がキャプチャしようとしたのは、AがBの前に解決される予定のシナリオであり、Aは遅れを伝えなければならない約束です。意味:私は 'pushA'が遅れを含むそれの仕事を完了することを望んでいますし、そして-and-only-thenは' pushB'を実行します。あなたの入力で実装された、更新されたフィドルがあります。これは私が探していたものに到達するのに役立ちました:https://jsfiddle.net/nam3cbaw/1/ – twip

関連する問題