2017-03-16 4 views
1

どのように私はループから抜け出すん。この例ループ内で一連の非同期操作を中断する方法はありますか?

Dojo FAQ: How can I sequence asynchronous operations?

function doNext(previousValue) { 
    var dfd = new Deferred(); 

    // perform some async logic; resolve the promise 
    setTimeout(function() { 
     var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1); 
     dfd.resolve(previousValue + next); 
    }, 50); 

    return dfd.promise; 
} 

var promise = doNext('a'); 

for (var i = 0; i < 9; i++) { 
    promise = promise.then(doNext); 
} 

promise.then(function (finalResult) { 
    // 'doNext' will have been invoked 10 times, each 
    // invocation only occurring after the previous one completed 

    // 'finalResult' will be the value returned 
    // by the last invocation of 'doNext': 'abcdefghijk' 
    console.log(finalResult); 
}); 

に続いて - doNextが一定の基準を満たしたときに、その後のdoNextの関数呼び出し処理を停止すなわち - 例えば、停止のために次の文字がD」のとき'と計算された値をその時点まで返しますか?

編集:これまで、遅延キャンセル()メソッドを使用しましたが、プロセスを強制終了して何も返しません。

setTimeout(function() { 
    var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1); 
    if(previousValue + next == 'abc') 
     dfd.cancel('abc'); 
    else 
    dfd.resolve(previousValue + next); 
}, 50); 

答えて

1

約束から返された値をチェックして、非同期要求を再度呼び出すかどうかを決定することができます。 forループにbreakを追加するようなものではありません。しかし結果はあなたが望むものになります。

すべて9 promise.thenが呼び出されますが、doNextは9回呼び出されません。以下は同じもののスニペットです。

for (var i = 0; i < 9; i++) { 
    promise = promise.then(function(val){ 
     return val === "abcd" ? val : doNext(val); 
    }); 
} 

これはループが存在しないと思われるかもしれません。これは、コールバック関数が呼び出される前にループが完了しているためです。しかし、非同期関数を呼び出す代わりに、コールバック関数は単純に値を返します。ループが素早く終了します。以下はJSBinへのリンクです。ここでタイムアウトを増やしていますが、最初は希望の結果が返されてからすぐに終了するまでに時間がかかります。

https://jsbin.com/qiwesecufi/edit?js,console,output

もう、あなたがチェックを行うことができる場所は、doNext関数自身の中にあります。

function doNext(previousValue) { 
    var dfd = new Deferred(); 

    if(previousValue === "abcd") 
     return previousValue; 

    // perform some async logic; resolve the promise 
    setTimeout(function() { 
     var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1); 
     dfd.resolve(previousValue + next); 
    }, 1000); 

    return dfd.promise; 
} 

希望しました。

1

常にすべてのアイテムを処理したい(または必要な数を同期して決定する)場合にのみ、reduce(またはpromise = promise.then(doNext))ループアプローチを使用してください。ループへ

任意の回数や任意のステップで抜け出す、再帰はより良いアプローチです:

function wait(t, v) { 
    var dfd = new Deferred(); 
    // asynchronously resolve the promise 
    setTimeout(function() { 
     dfd.resolve(v); 
    }, t); 
    return dfd.promise; 
} 

function doNext(previousValue) { 
    var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1); 
    return wait(50, previousValue + next); 
} 

function loop(v, i) { 
    if (i <= 0) return when(v); 
    if (v == "abc") return when("abc"); 
    return doNext(v).then(function(r) { 
     return loop(r, i-1); 
    }); 
} 

loop('a', 9).then(function (finalResult) { 
    console.log(finalResult); 
}); 
+0

は、私はあなたの例をしようとしていたが、二つの質問1) - 「とき」とは何ですか? 2)コードをステップ実行して、最終結果をコンソールに書き込むことはありません。 – erotavlas

+0

['when'](https://dojotoolkit.org/reference-guide/1.10/dojo/when.html)は、[' Promise.resolve'](https://developer.mozilla .org/ja-jp/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve)。最終的な結果に関しては、コードをテストしていませんが(もちろん、私が 'i'を渡すのを忘れたことに気がついたのですが)、確かにすべきです。 – Bergi

関連する問題