2016-09-24 6 views
1

JavaScriptでこのアルゴリズムを約束する方法を教えてください。Javascript:試行回数の後に条件を待つか中止することを約束します

// condition: some situation that is not true 
// interval: period to wait before trying again 
// retriesAllowed: maximum number of retries to make before aborting 
// retriesMade: number of retries made so far 
while() { 
    if (condition) return true; // indicates success 
    if (retriesMade < retriesAllowed) return false; // or throw an exception 
    ++retriesMade; 
    wait(interval); 
} 

それが実際に移動する前に、trueまたはfalseに解決するために、チェックを待たないので、これは、動作しません:

var check =() => { 
    if (condition) return true; // indicates success 
    if (retriesMade < retriesAllowed) return false; // or throw an exception 
    ++retriesMade; 
    setTimeout(check,interval) 
} 
check(); 
+0

[https://github.com/kriskowal/q](https://github.com/kriskowal/q) –

+1

@CodeSpirit [ネイティブの約束(https://developer.mozilla.org/ en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)を参照してください。 –

+0

これまでに何を把握できましたか?あなたが作った試みからスニペットを共有することはできますか? (スタックオーバーフローはコード作成サービスではありません。あなた自身の努力の一部を最初に入れておくことを期待しています) –

答えて

2

それが実際に移動する前に、trueまたはfalseに解決するために、チェックを待たないので、これは、動作しません。その

一部は失敗/終了条件が反転しているように見えるのかもしれので、conditionを確認する第一ラウンドの後、おそらく常に終了します:

その向こう
// retriesMade starts at 0, which is likely already less-than retriesAllowed 
if (retriesMade < retriesAllowed) return false; 

// probably should be 
if (retriesMade >= retriesAllowed) return false; 

待ち時間の欠如は、setTimeout()のような非同期動作を考慮して設計されています。周囲のコードは、結果を待たずに常に実行を続けます。

待機するのではなく、プロセスが実際に完了し、その情報を引き継ぐときに通知する方法を確立する必要があります。約束はそのための一つの選択肢です。

サイドノート:行動の完全な説明と、他のオプションはreturnまたはthrowを使用する代わりに、彼らは成功を知らせるresolve()reject()機能を提供し、彼らと「How do I return the response from an asynchronous call?

で提供されていますまたは失敗したとみなします。それらの.then()およびメソッドを使用して継続を設定できます。また

var tries = new Promise((resolve, reject) => { 
    var retriesMade = 0; 
    var interval = 1000; 

    var check =() => { 
     if (condition) { resolve(); } 
     if (retriesMade >= retriesAllowed) { reject(); } 
     ++retriesMade; 
     setTimeout(check, interval); 
    }); 

    check(); 
}); 

tries.then(
    () => console.log('success'), 
    () => console.log('failure') 
); 

、関数(untilLimited)で反復を含むだけでなく、必要に応じて、非同期であることが条件(exitUpon)を可能にする、より完全に約束を使用する代替バージョン。

function delay(milliseconds) { 
    return new Promise(function (resolve) { 
    setTimeout(resolve, milliseconds); 
    }); 
} 

function untilLimited(limit, waitTime, exitUpon) { 
    return Promise.resolve() 
    .then(exitUpon) 
    .then(result => { 
     if (result) return true; 
     if (!(--limit > 0)) return Promise.reject('Limit exceeded.'); 
     return delay(waitTime) 
     .then(() => untilLimited(limit, waitTime, exitUpon)) 
    }); 
} 

untilLimited(5, 500,() => false /* condition */) 
    .then(
    (result) => console.log('success', result), 
    (result) => console.log('failure', result) 
); 
+0

コールバックコードの周りに新しいプロミスをラップするだけではいけません。実際には*約束を使用するべきです – Bergi

+0

@Bergiあなたはそれが意味することを詳述できますか?私は、プロミスベースの 'setTimeout()'に相当するネイティブを認識していないので、いくつかのラッピングが避けられないようです。しかし、それはおそらく最小限に抑えることができます。 –

+0

はい、ただし、 'setTimeout'だけをラップして、何もしないで、アルゴリズムの約束を使用してください。 – Bergi

0

あなたはqライブラリ(または$qでを使用することができます反復オブジェクトを返すために、そしてバックグラウンドで間隔を実行してください。数回の試行後にconditionが満たされない場合は、約束を拒否してください。

Example for Angular

+0

これは良い答えではありません。角度はここでも重要ではありません –

+0

角度のないqライブラリを使用できます。 $ qは角度のラッパーです。コアライブラリーは同じように動作します – eavidan

関連する問題