【问题标题】:node.js synchronous requests for use in caching用于缓存的 node.js 同步请求
【发布时间】:2016-11-18 04:14:53
【问题描述】:

我的代码中有一个与缓存 API 结果有关的问题需要解决。我有一些像这样的 async.map:

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...
}

【问题讨论】:

    标签: javascript node.js asynchronous


    【解决方案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);
    

    【讨论】:

    • 是否保证按顺序运行系列?谢谢!
    • 是的,保证订单。如果您只使用.each,则无法保证它们将并行运行
    【解决方案2】:

    使用 Promises 代理和缓存 API 调用。使用 Promises 批处理 API 请求和缓存结果非常简单。以下代码小模块将现有的 expensiveAPI 调用包装在 Promise 中,并将解析结果缓存 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];
    }
    

    【讨论】:

    • 感谢您的回答!承诺request() 呼叫是否也适用于此代码?那时我不想使用request-promise() 库并将.then() 与它链接吗?
    • 是的。如果您的 API 请求使用 request-promise,那么您无需承诺 API 请求,因为它已经返回了一个承诺。
    猜你喜欢
    • 1970-01-01
    • 2018-10-31
    • 2018-02-14
    • 1970-01-01
    • 2017-04-13
    • 2016-05-20
    • 1970-01-01
    • 2014-12-27
    • 2015-02-10
    相关资源
    最近更新 更多