From d1c50b0c7e17a8ca6f8bae11169167b51fe2e5df Mon Sep 17 00:00:00 2001 From: cnzgray Date: Tue, 13 Nov 2018 10:57:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E6=A1=88:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=B8=80=E4=B8=AA`tryGet`=E6=96=B9=E6=B3=95=E5=88=B0cache?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E4=B8=AD=E3=80=82=20(#1130)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在抓取一些博客或者论坛的时候,有时候会系统抓取内容页面作为desc。 大多数的做法是获取子页面的地址,然后判断是否已经缓存结果,如果没有则获取,然后设置到缓存中。 这做法固然没有问题,这里只是提供一种新的思路,以将子页面的抓取逻辑独立出去便于逻辑实现。 使用方法: ``` const loadContent = async (link) => { // 执行页面加载,解析内容等操作。 // 最终返回一个结果,该结果将被缓存。 return result; } const result = await ctx.cache.tryGet(link, async () => loadContent(link), 3 * 60 * 60); ``` --- middleware/lru-cache.js | 21 +++++++++++++++++++++ middleware/redis-cache.js | 21 +++++++++++++++++++++ routes/typora/changelog.js | 16 +++------------- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/middleware/lru-cache.js b/middleware/lru-cache.js index 4be27b186..838cc45b9 100644 --- a/middleware/lru-cache.js +++ b/middleware/lru-cache.js @@ -36,6 +36,27 @@ module.exports = function(options = {}) { memoryCache.set(key, value, maxAge * 1000); } }, + + /** + * + * try get from cache. + * if not exists use `getValue` function to get value, and put into cahche. + * + * @param key cache key + * @param getValueFunc a function to get value. call it when key not exists. + * @param maxAge + * + * @returns {Promise} + */ + tryGet: async function(key, getValueFunc, maxAge) { + let v = await this.get(key); + if (!v) { + v = await getValueFunc(); + this.set(key, v, maxAge); + } + + return v; + }, }; return async function cache(ctx, next) { diff --git a/middleware/redis-cache.js b/middleware/redis-cache.js index 0115fe9fa..6ec659ee9 100644 --- a/middleware/redis-cache.js +++ b/middleware/redis-cache.js @@ -57,6 +57,27 @@ module.exports = function(options = {}) { await redisClient.setex(key, maxAge, value); } }, + + /** + * + * try get from cache. + * if not exists use `getValue` function to get value, and put into cahche. + * + * @param key cache key + * @param getValueFunc a function to get value. call it when key not exists. + * @param maxAge + * + * @returns {Promise} + */ + tryGet: async function(key, getValueFunc, maxAge) { + let v = await this.get(key); + if (!v) { + v = await getValueFunc(); + this.set(key, v, maxAge); + } + + return v; + }, }; return async function cache(ctx, next) { diff --git a/routes/typora/changelog.js b/routes/typora/changelog.js index b848f6b1f..e0309d18d 100644 --- a/routes/typora/changelog.js +++ b/routes/typora/changelog.js @@ -14,13 +14,7 @@ module.exports = async (ctx) => { const $ = cheerio.load(response.data); - const parseContent = async (link) => { - // Check cache - const cache = await ctx.cache.get(link); - if (cache) { - return Promise.resolve(JSON.parse(cache)); - } - + const loadContent = async (link) => { const response = await axios({ method: 'get', url: link, @@ -36,17 +30,13 @@ module.exports = async (ctx) => { // const author = $('.post-meta span').text(); const html = $('#pagecontainer').html(); - const result = { + return { title: title, link: link, guid: link, pubDate: pubDate, description: html, }; - - ctx.cache.set(link, JSON.stringify(result), 3 * 60 * 60); - - return result; }; const items = await Promise.all( @@ -55,7 +45,7 @@ module.exports = async (ctx) => { .map(async (item) => { const node = $('a', item); const link = node.attr('href'); - const result = await parseContent(link); + const result = await ctx.cache.tryGet(link, async () => loadContent(link), 3 * 60 * 60); return Promise.resolve(result); })