在 ES6 中修改新请求对象的 URL

Posted

技术标签:

【中文标题】在 ES6 中修改新请求对象的 URL【英文标题】:Modify the URL of a new Request Object in ES6 【发布时间】:2017-08-17 16:42:39 【问题描述】:

我只是在玩Fetch API,但遇到了一些我似乎无法找到答案的东西。如果我像这样创建一个新的请求对象:

let request = new Request('http://www.foo.com', 
  method: 'GET',
  mode: 'no-cors',
  headers: new Headers(
'Content-Type': 'application/x-www-form-urlencoded'
  )
);

如果我随后尝试修改 URL(向其附加查询字符串),我会在浏览器中收到错误消息 (Cannot assign to read only property)。我知道通常使用对象,您可以将writable 设置为“True”,但这对请求对象是否同样有效?

我问的原因是我试图将查询字符串附加到 URL 的末尾。这些options 在另一个对象中,我将它的值连接到一个字符串中,因此它类似于:

number=1&id=130&foo=bar

我是否试图过度设计我在这里所做的事情?

【问题讨论】:

当您说“修改 URL(向其附加查询字符串)”时,您尝试使用的代码是什么样的?如果你省略mode: 'no-cors',那么你能修改URL吗?你为什么使用mode: 'no-cors'?使用它告诉浏览器根本不允许您的 javascript 代码访问响应。因此,即使请求成功发出,mode: 'no-cors' 也会阻止您对响应执行任何操作。 可以在创建Request对象之前将查询字符串放在url上。 抱歉我把模式设置为no-cors,因为我是在本地开发的。我只是想在 API Gateway 中设置 URL。我将使用您请求的代码进行更新。 @sideshowbarker 如果我删除 no-cors 我会收到以下错误,No 'Access-Control-Allow-Origin' header is present on the requested resource 因为 localhost 无法访问 URL @jfriend00 谢谢,我觉得我有点厚,你说得对。我没想过先简单地编辑 URL,然后在创建新请求对象时添加包含修改后 URL 的变量而不是 URL! 【参考方案1】:

您可以将旧请求中的所有属性复制到具有新 url 的新请求中,如下所示:

const init =  
  method: 'GET',
  mode: 'no-cors',
  headers: new Headers(
    'Content-Type': 'application/x-www-form-urlencoded'
  )
;
const oldRequest = new Request("https://old-url.com", init);
const newRequest = new Request("https://new-url.com", oldRequest);

console.log(newRequest.mode === oldRequest.mode); // true
console.log(newRequest.headers.get('Content-Type') === oldRequest.headers.get('Content-Type')); // true
console.log(newRequest.method === oldRequest.method); // true

【讨论】:

这是一个更好的响应,应该是选定的响应。【参考方案2】:

Request 对象在设计上是不可变的,不要试图改变它。

我希望clone() 实例方法接受的选项能够调整克隆对象,但事实并非如此。所以我想出了这个功能:

function appendQuery(urlOrReq, queryString) 
    // make sure we deal with a Request object even if we got a URL string
  const req = urlOrReq instanceof Request ? urlOrReq : new Request(urlOrReq);

  const 
    cache, credentials, headers, integrity, method,
    mode, redirect, referrer, referrerPolicy, url, body
   = req;

  // Don't add query string if there's none
  const urlWithQuery = url + (!queryString ? '' : '?' + queryString);

  return new Request(urlWithQuery, 
    cache, credentials, headers, integrity, method,
    mode, redirect, referrer, referrerPolicy, body
  )

在 TypeScript 中也是一样的(只是第一行不同):

function appendQuery(urlOrReq: RequestInfo, queryString?: string): Request 
    // make sure we deal with a Request object even if we got a URL string
  const req = urlOrReq instanceof Request ? urlOrReq : new Request(urlOrReq);

  const 
    cache, credentials, headers, integrity, method,
    mode, redirect, referrer, referrerPolicy, url, body
   = req;

  // Don't add query string if there's none
  const urlWithQuery = url + (!queryString ? '' : '?' + queryString);

  return new Request(urlWithQuery, 
    cache, credentials, headers, integrity, method,
    mode, redirect, referrer, referrerPolicy, body
  )

它是这样工作的:

const req = new Request('https://google.com')
appendQuery(req, 'foo=42')
// => Request method: "GET", url: "https://google.com?foo=42", headers: Headers, destination: "", referrer: "about:client", …

【讨论】:

Request object is immutable by design 是不可变的,但是你可以改变headers :)) 我觉得做url的url实例会更方便,所以你可以轻松修改searchParams

以上是关于在 ES6 中修改新请求对象的 URL的主要内容,如果未能解决你的问题,请参考以下文章

ES6中常用的10个新特性讲解

ES6的新特性

ES6浅谈--const,数组解构

ES6(六)—— Object

ES6基础入门教程(九)修改对象的键值

ES6对象属性名简洁表示法和表达式对象新方法属性的遍历