在Node.js中缓存请求

时间:2018-09-17 13:48:27

标签: node.js express node-request

这是运行良好的实际代码,仅向具有某些参数的api发送请求:

var request = require('request');
var express = require('express');
var router = express.Router();

/* GET data by sportId */
router.get('/:locale/:sportId/:federationId/:date', function(req, res) {
    var date = req.params.date;
    var locale = req.params.locale;
    var sportId = req.params.sportId;
    var federationId = req.params.federationId;

   request(getEventsOptions(sportId, federationId, date, locale), function(error, response, body) {
    res.send(body);
   });
});

// get options for request
function getEventsOptions(sportId, federationId, date, locale)
{
    return {
        url: `http://myapi.com/sporting-event/sport/${sportId}/date-from/${date}`,
       headers: {
         'accept': 'application/json',
         'dateTo': date,
         'federationIds': federationId,
         'X-Application-ID': 'sporter',
         'Accept-Language': locale,
     }
 };

}

我收到一个对象数组(每个对象都是具有唯一eventId的体育游戏)。因此,每当我调用此路由时,我都会对api进行新的调用,我只想在事件的对象不同时(例如,如果游戏的分数已更改)询问api。您对如何做到这一点有想法吗?

1 个答案:

答案 0 :(得分:0)

这是memoization服务的目的。由于getEventsOptions接受标量参数,因此简化了应记住的方式;缓存键可以根据字符串化参数计算得出,例如Lodash memoize或类似的实现方式:

function memoize(fn, getCacheKey = ([firstArg]) => firstArg) {
  const cache = new Map();
  return (...args) => {
    const cacheKey = getCacheKey(args);

    if (!cache.has(cacheKey))
      cache.set(cacheKey, fn(...args));

    return cache.get(cacheKey);
  }
}

最好使用Promise,因为可以将Promise对象作为结果缓存,而使用基于回调的API则很难做到这一点。已通过官方request软件包为request-promise提供了承诺:

const request = require('request-promise');

function getEvents(sportId, federationId, date, locale)
{
    const options = {
        url: `http://myapi.com/sporting-event/sport/${sportId}/date-from/${date}`,
       headers: {
         'accept': 'application/json',
         'dateTo': date,
         'federationIds': federationId,
         'X-Application-ID': 'sportytrader',
         'Accept-Language': locale,
     };

     return request(options);
};

const getCachedEvents = memoize(
  getEvents,
  (...args) => JSON.stringify(args)
);

...

getCachedEvents(sportId, federationId, date, locale))
.then(body => res.send(body)
.catch(next);

请注意,由于JSON.stringify的工作方式,这可能会影响请求的缓存方式,例如undefinednull参数没有区别。