Javascript 如何使用不同的URL复制请求对象?

Javascript 如何使用不同的URL复制请求对象?,javascript,fetch-api,Javascript,Fetch Api,我正在写一个关于fetch的包装,我想在发出请求之前向URL添加一些内容,例如识别查询参数。我不知道如何使用与原始URL不同的URL复制给定的请求对象。我的代码如下所示: // My function which tries to modify the URL of the request function addLangParameter(request) { const newUrl = request.url + "?lang=" + lang; return new Re

我正在写一个关于
fetch
的包装,我想在发出请求之前向URL添加一些内容,例如识别查询参数。我不知道如何使用与原始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));
}
我尝试将原始请求作为
请求
构造函数的第二个参数,如下所示:

function addLangParameter(request) {
    const newUrl = request.url + "?lang=" + lang;
    return new Request(newUrl, request);
}
它似乎复制了旧请求的大多数属性,但似乎没有保留旧请求的
正文。比如说,

const request1 = new Request("/", { method: "POST", body: "test" });
const request2 = new Request("/new", request1);
request2.text().then(body => console.log(body));
我希望记录“test”,但它会记录空字符串,因为正文没有被复制

我是否需要做一些更明确的事情来正确复制所有属性,或者是否有一个好的快捷方式可以为我做一些合理的事情


我使用的是polyfill,但在最新的Chrome浏览器中使用了polyfill和原生的
fetch
实现进行了测试。

看起来您最好的选择是使用
body
接口读取正文,该接口请求实现:

这只能异步完成,因为底层的“consume body”操作总是异步读取并返回承诺。像这样的方法应该会奏效:

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请求中指定任何主体,甚至是零长度的主体都是不正确的。我认为检查原始请求是否设置了
内容类型
是一个准确的代理,它是否有主体,这是我们真正需要确定的不显示伪代码:显示真实代码。@Mike'Pomax'Kamermans我添加了实际代码。我认为这会使理解实际问题变得更加困难,也许会有所帮助。你的新代码通过在代码本身中显示你对请求对象的使用,而不是更加困难,实际上让你的问题变得显而易见。看起来这在github/fetch polyfill中目前不起作用(这没有适当地设置
内容类型
标题),但这在Chrome中非常有效。谢谢!正确的
正文
赋值可能是
const body=['GET','HEAD']。包括(r.method)?未定义:wait r.blob()
。†MDN声明:“使用GET或HEAD方法的请求不能有正文。”