2016-11-17 44 views
0

我有一個問題需要在我的代碼中解決,這與緩存API結果有關。我有一些async.map像這樣:node.js在緩存中使用同步請求

for(var user of allUsers) { 
    var requestList = fill(cache, locations, apiUrl, cacheMap); 

    async.map(requestList, function(obj, callback) { 
     // ... 
    }, function(err, results) { 
     // PUT RESULTS INTO A CACHE 
    }); 
} 

功能fill只是看起來在緩存中,看是否在locations的位置存在,並且它不是爲將要運行我的API請求的URL。

但是我意識到緩存對於我的方法根本沒有多大用處,因爲我的代碼會調度async.map並立即開始下一個循環迭代fill,這意味着緩存將不會在用戶的每次迭代中同步。

我該如何去確保用戶的每次迭代都有最後一位用戶的緩存更新版本?我需要非常聰明地使用我有限的API調用,所以如果有重複的請求我想請求一次,那麼在稍後的請求中從緩存中取出結果。

我現在唯一經歷的是將一個同步的請求,而不是一個async.map,但我知道這違背了node.js的設計。

for(var user of allUsers) { 
    var requestList = fill(cache, locations, apiUrl, cacheMap); 

    // sync map instead 
    requestList.map(function(obj) { 
     var res = sync-request(obj) 
     // put request result into cache 
    }); 

    // cont... 
} 

回答

1

你可以使用async.eachSeries迭代allUsers。這將按順序逐步完成並保持異步。

async.eachSeries(allUsers, (user, done) => { 
    const requestList = fill(cache, locations, apiUrl, cacheMap); 

    async.map(requestList, (obj, callback) => { 
    // .. 

    callback(null, requestResult); 
    }, (err, results) => { 
    // PUT RESULTS INTO A CACHE 

    done(null, results); 
    }); 
}, cb); 
+0

它是否保證按順序運行系列?謝謝! –

+0

是的,它會保證順序。如果你只使用'.each',那麼它將不會得到保證,因爲它們將平行運行 – cejast

1

使用承諾來代理和緩存API調用。使用Promise批量API請求並緩存結果非常簡單。下面的小代碼模塊包含Promise中的現有expensiveAPI調用,並將解析後的結果緩存60秒。

// Existing module to call the expensive API 
// using the standard callback pattern 
var expensiveApi = require("./expensiveApi"); 
// Using bluebird promise library 
// See http://bluebirdjs.com/docs/api-reference.html 
var Promise = require("bluebird"); 

// Promisify the existing callback 
expensiveApi = Promise.promisify(expensiveApi); 
// Calls to the API will now return a Promise 

// A cache for the Promises 
var cache = {}; 

module.exports = function expensiveApiWithPromises(item) { 
    // Check whether a cached Promise already exists 
    if (cache[item]) { 
    // Return it to the caller 
    return cache[item]; 
    } 

    // Promise is not in the cache 
    cache[item] = expensiveApi(item) 
    .then(function(result) { 
    // Promise has resolved 
    // set the result to expire 
    setTimeout(function() { 
     delete cache[item]; 
    }, 60 * 1000); // 60 seconds expiry 
    // Return the result 
    return result; 
    }) 
    .catch(function(err) { 
    // Promise rejected with an error 
    // Reset the cache item 
    delete cache[item]; 
    // Propagate the error 
    throw err; 
    }); 

    // Return the newly created cached Promise 
    return cache[item]; 
} 
+0

感謝您的回答!這個代碼也會促使'request()'調用工作嗎?那時我不想使用'request-promise()'庫並鏈接'.then()'? –

+0

是的。如果您的API請求使用'request-promise',那麼您不需要提交API請求,因爲它已經返回一個承諾。 –