【问题标题】:Express middleware caching快速中间件缓存
【发布时间】:2015-07-16 06:29:08
【问题描述】:

我正在尝试使用 express 中间件实现一些缓存,这似乎工作得很好,但我在某个地方陷入了无限循环。

在我的路由器中,我必须遵循以下路线:

router.get('/test', [middleware.cache.cache('1 day', true), controllers.test]);

middleware.cache.cache 看起来像这样:

module.exports.cache = function(time, global) {
    // Do some stuff with the time here

    return function cache(req, res, next) {
        // Keep a copy of the actual send method
        res._send = res.send;

        // Overwrite the res.send function
        res.send = function(obj) {
             console.log('[' + res.statusCode + '] Cache: ' + redisKey);

             // Get the key from redis
             redis.get(redisKey)
                .then(function(result) {
                    result = JSON.parse(result);

                    if(!_.isNull(result)) {
                        console.log('Expired cache found');

                        // Send initial object
                        return res._send(obj);
                    } else {
                        console.log('Cache found');

                        // Send back cached object
                        return res._send(result.obj);
                    }
                } else {
                    console.log('No data found');

                    storeInRedis(redisKey, obj, time);

                    // Send initial object
                    return res._send(obj);
                }
            })
            .fail(function(err) {
                console.log(err);

                return res._send(obj);
            });
        };

        next();
    };
};

我得到的输出如下所示:

[200] Cache: cache_global_test
Cache found
[200] Cache: cache_global_test
Cache found
...

所以我怀疑当我调用 res._send(obj) 时,它实际上指的是我刚刚覆盖的原始 res.send。这当然会导致无限循环。 但我真的找不到任何解决方案。

【问题讨论】:

标签: node.js express middleware


【解决方案1】:

res._send = res.send 不会创建副本。

它会创建一个对您稍后要更改的函数的引用。

要创建副本,请使用:https://www.npmjs.com/package/clone

为什么需要“覆盖 res.send 函数”res.send 函数?

您可以在redis.get(redisKey).then 中使用next() 来实现您想要的。

我认为像这样更改send 可能是一件危险的事情,因为它是一个内置的express 方法并且您的“最后一个函数”和其他开发人员希望它按照@987654329 中描述的方式运行@文档。

最好将isCachedcache 属性添加到带有缓存中间件的res,然后在“最后一个函数”中进行相应的操作,使其明确意识到可能存在缓存值和缓存中间件。

【讨论】:

  • 我需要覆盖它,因为我希望对程序的其余部分进行最小的更改,例如,在controllers.test 中,我调用res.status(200).send(...)
  • redis.get().then 中使用next() 只会继续中间件链,这不是我想要的,因为最后一个函数是从数据库中检索项目的控制器,因此我为什么插入中间件。
  • 可以对最后一个函数进行修改吗?
  • 我宁愿不这样做,使用中间件的目的是让它可以插入到任何路由中而无需任何其他更改。
  • 我想评论一下这个答案的重要性。它为我们节省了数小时的调试时间。我什至在博客中链接到它:medium.com/the-node-js-collection/…
猜你喜欢
  • 2019-06-19
  • 2014-12-03
  • 2015-08-12
  • 2018-09-17
  • 1970-01-01
  • 2018-10-11
  • 1970-01-01
  • 2022-07-19
相关资源
最近更新 更多