我想這是比那些典型的「幫助我的代碼不工作」的類型更體系結構的問題。
讓我解釋你的要求。
問:我想緩存一些不太可能改變的HTTP請求的響應,我希望這些緩存的響應每15秒刷新一次。可能嗎?
- 答:是的,你要感謝Javascript
是單線程的事實,所以它將是非常簡單的。
這裏有一些基礎知識。 NodeJS
是一個事件驅動的框架,這意味着在一個時間點它將只執行一段代碼,直到完成。
如果在此過程中遇到任何aysnc
調用,它將調用它們並向event-loop
添加事件以在接收到響應時說「callback
」。代碼例程完成後,它會彈出隊列中的下一個事件來運行它們。
基於這些知識,我們知道我們可以通過構建一個function
來實現此目的,以便每次過期時僅觸發1個異步調用update
,cached-responses
。如果一個異步調用已經在執行,那麼只需將它們的回調函數放入一個隊列即可。這樣可以避免多次異步調用來獲取新結果。
我不熟悉async
模塊,所以我提供了一個使用promises
代替的僞代碼示例。
僞代碼:
var fetch_queue = [];
var cached_result = {
"cached_result_1": {
"result" : "test",
"expiry" : 1501477638 // epoch time 15s in future
}
}
var get_cached_result = function(lookup_key) {
if (cached_result.hasOwnProperty(lookup_key)) {
if (result_expired(cached_result[lookup_key].expiry)) {
// Look up cached
return new Promise(function (resolve) {
resolve(cached_result[lookup_key].result);
});
}
else {
// Not expired, safe to use cached result
return update_result();
}
}
}
var update_result = function() {
if (fetch_queue.length === 0) {
// No other request is retrieving an updated result.
return new Promise(function (resolve, reject) {
// call your API to get the result.
// When done call.
resolve("Your result");
// Inform other requests that an updated response is ready.
fetch_queue.forEach(function(promise) {
promise.resolve("Your result");
})
// Compute the new expiry epoch time and update the cached_result
})
}
else {
// Create a promise and park it into the queue
return new Promise(function(resolve, reject) {
fetch_queue.push({
resolve: resolve,
reject: reject
})
});
}
}
get_cached_result("cached_result_1").then(function(result) {
// reply the result
})
注:正如其名稱所暗示的代碼是不實際可行的解決方案,但這個概念是存在的。
值得注意的是,setInterval
是一種方式去但它並不能保證函數將被準確地調用在15秒標記。 API只能確保在預期的時間之後會發生某些事情。
鑑於所提出的解決方案將確保只要cached result
已過期,下一個查找它的人將執行請求,並且以下請求將等待最初的請求返回。