我正在编写一个包装器fetch
,我想在发出请求之前向URL添加内容,例如识别查询参数.我无法弄清楚如何Request
使用与原始URL不同的URL 制作给定对象的副本.我的代码看起来像:
// My function which tries to modify the URL of the request function addLangParameter(request) { const newUrl = request.url + "?lang=" + lang; return new Request(newUrl, /* not sure what to put here */); } // My fetch wrapper function myFetch(input, init) { // Normalize the input into a Request object return Promise.resolve(new Request(input, init)) // Call my modifier function .then(addLangParameter) // Make the actual request .then(request => fetch(request)); }
我尝试将原始请求作为第二个arguent放到Request
构造函数中,如下所示:
function addLangParameter(request) { const newUrl = request.url + "?lang=" + lang; return new Request(newUrl, request); }
这似乎复制了旧请求的大部分属性,但似乎并不保留body
旧请求.例如,
const request1 = new Request("/", { method: "POST", body: "test" }); const request2 = new Request("/new", request1); request2.text().then(body => console.log(body));
我希望记录"test",但它会记录空字符串,因为正文不会被复制.
我是否需要做一些更明确的事情才能正确复制所有属性,或者是否有一个很好的快捷方式可以为我做一些合理的事情?
我正在使用github/fetch polyfill,但已经fetch
在最新的Chrome中使用polyfill和native 实现进行了测试.
看起来你最好的选择是使用Body
Requests实现的接口来读取正文:
https://fetch.spec.whatwg.org/#body
这只能异步完成,因为底层的"消耗体"操作总是异步读取并返回一个promise.这样的事情应该有效:
const request = new Request('/old', { method: 'GET' }); const bodyP = request.headers.get('Content-Type') ? request.blob() : Promise.resolve(undefined); const newRequestP = bodyP.then((body) => new Request('/new', { method: request.method, headers: request.headers, body: body, referrer: request.referrer, referrerPolicy: request.referrerPolicy, mode: request.mode, credentials: request.credentials, cache: request.cache, redirect: request.redirect, integrity: request.integrity, }) );
完成后,newRequestP
将是一个解决您想要的请求的承诺.幸运的是,fetch无论如何都是异步的,因此你的包装器不应该受到严重阻碍.
(注意:使用.blob()
没有正文的请求读取正文似乎返回零长度的Blob对象,但是在GET或HEAD请求中指定任何正文,甚至是零长度的正文都是不正确的.相信检查原始请求是否已Content-Type
设置是一个准确的代理,它是否有一个正文,这是我们真正需要确定的.)