2016-06-27 27 views
1

用例 - 獲取一堆網址並緩存結果。那些完成速度很快(比如說500ms)的程序會被合併到這個過程中,任何需要比這個過程更長的時間才能完成並保存到緩存中,這樣下一次(大約10分鐘後,在我們的應用程序中)它們就會進入緩存。Promise.some()有超時?

我希望能夠做些類似於Promise.someWithTimeout(promises, timeout)的地方,其結果是在超時過期之前完成的解析值數組。 (Promise.some()是非常接近所花費的計數不超時)

喜歡的東西

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

這裏每個承諾看起來像

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

的想法是,如果該URL回來快速我們使用它,如果它需要更長時間我們保釋,但仍然緩存結果,所以下次通過我們擁有它。所以rp()超時將比Promise.someWithTimeout()一個更長一個

有沒有人寫了一個庫來做到這一點(我找不到一個),還是有更好的模式?我雖然關於使用Promise.all().timeout().finally()的承諾將他們的結果存入一個數組,但它不合理,因爲我不能完全放下手指。

+0

是否每次通過包括相同的「網址的束」或它們可以從通變化通過? –

回答

3

對於一次性編碼,就可以啓動兩個獨立的承諾鏈,並使用一個標誌來判斷是否超時已經發生:

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

如果要打包這個功能集成到一個方法有能力訪問超時事件(即使在超時之後)以及最終結果的事實(例如,您可以緩存它們),那麼您必須使用其中包含多個信息的內容來解決。通過使用可包含多條信息的對象進行解析,以下是一種允許訪問超時和最終數據的方法。

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(promises).then(()=> save to cache )離開它自己和一個Promise.delay(500)。然後(()=>返回Promise.some(數組)),並使用結果將是最佳的解決方案。 –

+0

即使響應早於此響應,您的建議也會強制延遲500毫秒。我同意保留在緩存中的'Promise.all()'運行在它自己的位置是合理的。然後,爲超時使用相同的承諾和計時器。 – jfriend00