2016-06-27 16 views
1

ユースケース - 一連のURLを取得し、結果をキャッシュします。高速で完了したもの(例えば500ms)がこのパスに組み込まれます。それよりも時間がかかり、キャッシュに保存されるので、次回(アプリで10分後)にキャッシュに保存されます。Promise.some()にタイムアウトがありますか?

私はPromise.someWithTimeout(promises, timeout)のようなことをしたいと思っています。結果は、タイムアウトの期限が切れる前に完了した解決された値の配列です。

約束のそれぞれがアイデアは、URLが戻ってきた場合ということで

return memcache.getAsync(keyFromUrl(url)) 
.then((cacheRes) => { 
    if(cacheRes) return cacheRes; 
    //not in cache go get it 
    return rp(url) 
    .then((rpRes) => { 
    //Save to cache but don't wait for it to complete 
    memcache.setAsync(keyFromUrl(url), rpRes, 86400).catch((e) => { /*error logging*/ }) 
    return rpRes; 
    }) 
}) 

のように見えます

Promise.someWithTimeout([promises], <timeout value>) 
.then((results) => { 
    //stuff 
}) 

のような(Promise.some()が、それはカウントされませタイムアウトを取ることにより、実際に近いです)

何か私たちがそれを使用するのは早いですが、それは時間がかかりますが、結果がまだキャッシュされているので、次回にはそれを持っています。だからrp()タイムアウトは、Promise.someWithTimeout()よりずっと長くなります

これを行うためのライブラリを書いた人は誰ですか(見つけられません)、またはより良いパターンがありますか?私は約Promise.all().timeout().finally()を約使用して約束しているが、その結果を配列に隠しているが、私の指を置くことができない理由のために正しいと感じていない。

+0

は各パスは同じ「URLの束」を含むか、またはそれらを渡すために、パスごとに異なることができますか? –

答えて

3

ワンオフ・コーディングでは、2本の別々の約束チェーンを開始し、タイムアウトがすでに起こったかどうかを確認するためにフラグを使用することができます:あなたは一つの方法に、この機能をパッケージ化したい場合は

var timedOut = false; 
// your regular code 
Promise.all(...).then(function() { 
    // cache the result, even if it came in after the timeout 

    if (!timedOut) { 
     // if we didn't time out, then show the response 
    } 
}); 

Promise.delay(1000).then(function() { 
    timedOut = true; 
    // do whatever you want to do on the timeout 
}); 

とタイムアウトした後にタイムアウトした後でも最終的な結果にアクセスできる(例えばキャッシュすることができるように)ために、複数の情報が含まれているもので解決する必要があります。複数の情報を含むことができるオブジェクトで解決することによって、タイムアウトと最終的なデータの両方へのアクセスを可能にする1つの方法があります。

Promise.someWithTimeout = function(promiseArray, cnt, timeout) { 
    var pSome = Promise.some(promiseArray, cnt).then(function(results) { 
     return {status: "done", results: results}; 
    }); 
    var pTimer = Promise.delay(cnt).then(function() { 
     return {status: "timeout", promise: pSome} 
    }); 
    return Promise.race([pSome, pTimer]); 
} 

// sample usage 
Promise.someWithTimeout(arrayOfPromises, 3, 1000).then(function(result) { 
    if (result.status === "timeout") { 
     // we timed out 
     // the result of the data is still coming when result.promise is resolved if you still want access to it later 
     result.promise.then(function(results) { 
      // can still get access to the eventual results here 
      // even though there was a timeout before they arrived 
     }).catch(...); 
    } else { 
     // result.results is the array of results from Promise.some() 
    } 
}); 

+0

@JohnPetitt - ここのオプションについてどう思いますか?これはあなたの質問に答えるか、あなたに有用なオプションを与えますか? – jfriend00

+0

これは理にかなっています。今は解決された約束がすべての約束事を配列に入れて、Promise.all(約束)したのと同じ結果を返すことを覚えています。 )Promise.delay(500).then(()=> Promise.some(array)を返します)、結果を最適なソリューションに使用することができます。 –

+0

あなたの提案は、応答がそれより早く戻っても、500msの遅延を強制します。私は、 'Promise.all()'がキャッシュ上に保存するためにそれ自身の上で実行するように残されていることは意味があることに同意します。その後、あなたのタイムアウトのためにタイマーと組み合わせて同じ約束を使用してください。 – jfriend00

関連する問題