缓存
Got实现了RFC 7234兼容的HTTP缓存,它可以在内存中开箱即用,并且可以很容易地插入各种存储适配器。
新的缓存条目直接从缓存中提供,过时的缓存条目使用If-None-Match
/ If-Modified-Since
头重新验证。
你可以在cacheable-request
文档中阅读更多关于底层缓存行为的信息。
你可以使用JavaScript的Map
类型作为内存缓存:
| import got from "got";
const map = new Map();
let response = await got("https://sindresorhus.com", { cache: map });
console.log(response.isFromCache);
//=> false
response = await got("https://sindresorhus.com", { cache: map });
console.log(response.isFromCache);
//=> true
|
Got在内部使用Keyv来支持各种存储适配器。
对于更可伸缩的东西,您可以使用官方Keyv存储适配器:)
| $ npm install @keyv/redis
|
| import got from "got";
import KeyvRedis from "@keyv/redis";
const redis = new KeyvRedis("redis://user:pass@localhost:6379");
await got("https://sindresorhus.com", { cache: redis });
|
Got支持任何遵循Map API的东西,因此编写自己的存储适配器或使用第三方解决方案都很容易。
例如,以下都是有效的存储适配器:
| const storageAdapter = new Map();
await got("https://sindresorhus.com", { cache: storageAdapter });
|
| import storageAdapter from "./my-storage-adapter";
await got("https://sindresorhus.com", { cache: storageAdapter });
|
| import QuickLRU from "quick-lru";
const storageAdapter = new QuickLRU({ maxSize: 1000 });
await got("https://sindresorhus.com", { cache: storageAdapter });
|
View the Keyv docs for more information on how to use storage adapters.
高级缓存机制
request
函数可能返回一个IncomingMessage
类的实例。
| import https from "node:https";
import { Readable } from "node:stream";
import got from "got";
const getCachedResponse = (url, options) => {
const response = new Readable({
read() {
this.push("Hello, world!");
this.push(null);
},
});
response.statusCode = 200;
response.headers = {};
response.trailers = {};
response.socket = null;
response.aborted = false;
response.complete = true;
response.httpVersion = "1.1";
response.httpVersionMinor = 1;
response.httpVersionMajor = 1;
return response;
};
const instance = got.extend({
request: (url, options, callback) => {
return getCachedResponse(url, options);
},
});
const body = await instance("https://example.com").text();
console.log(body);
//=> "Hello, world!"
|
If you don't want to alter the request
function, you can return a cached response in a beforeRequest
hook:
| import https from "node:https";
import { Readable } from "node:stream";
import got from "got";
const getCachedResponse = (url, options) => {
const response = new Readable({
read() {
this.push("Hello, world!");
this.push(null);
},
});
response.statusCode = 200;
response.headers = {};
response.trailers = {};
response.socket = null;
response.aborted = false;
response.complete = true;
response.httpVersion = "1.1";
response.httpVersionMinor = 1;
response.httpVersionMajor = 1;
return response;
};
const instance = got.extend({
hooks: {
beforeRequest: [
(options) => {
return getCachedResponse(options.url, options);
},
],
},
});
const body = await instance("https://example.com").text();
console.log(body);
//=> "Hello, world!"
|
If you want to prevent duplicating the same requests, you can use a handler instead.
| import got from "got";
const map = new Map();
const instance = got.extend({
handlers: [
(options, next) => {
if (options.isStream) {
return next(options);
}
const pending = map.get(options.url.href);
if (pending) {
return pending;
}
const promise = next(options);
map.set(options.url.href, promise);
promise.finally(() => {
map.delete(options.url.href);
});
return promise;
},
],
});
const [first, second] = await Promise.all([
instance("https://httpbin.org/anything"),
instance("https://httpbin.org/anything"),
]);
console.log(first === second);
//=> true
|