为什么在获取响应上使用解构赋值会导致 .json() 方法消失?

Why does using a destructuring assignment on a fetch response cause the .json() method to disappear?

感谢您抽出宝贵时间查看此内容。我 运行 遇到了一些意想不到的行为,我在 aws lambda 中工作时无法弄清楚。

我正在执行一个获取,然后根据它是成功还是失败做一些不同的事情,如果一切都符合标准,最终我想使用 fetch.json() 方法。我正在使用 await 来制作我的 lambda 处理程序的内部 "synchronous."

当我将获取的结果分配给一个变量然后检查它时,一切都很好。但是我喜欢整洁的代码,所以我决定使用解构赋值,突然事情开始崩溃了。

为了证明我的困惑,我提供了一个代码片段来重复这个问题并显示五个不同的东西 - 前两个有效,其余的中断。

在第三个例子中,"r"是一个空对象。其余的操作员破坏了它,我不明白。它是否正在创建一个新对象并拒绝复制属性?解构发生时属性不存在吗?如果是这样,为什么 ok 和 status 会正确解构?

四只是三的问题的简化示例。

5也让我很困惑,因为我能够得到json方法,但是当我尝试执行它时它抛出一个非法调用异常。

下面包含的代码段:

const one = async () => {
  const r = await fetch('https://reqres.in/api/users?page=2');
  console.log(await r.json());
}

const two = async () => {
  const r = await fetch('https://reqres.in/api/users?page=2');
  const { ok } = r;
  console.log(await r.json());
  console.log(ok);
}

const three = async () => {
  const { ok, status, ...r } = await fetch('https://reqres.in/api/users?page=2');
  try {
    console.log(await r.json());
  } catch (e) {
     console.log(e);
     console.log(ok);
     console.log(status);
     console.log(r);
  }
}

const four = async () => {
  const { ...r } = await fetch('https://reqres.in/api/users?page=2');
  console.log(r);
}

const five = async () => {
  const { json } = await fetch('https://reqres.in/api/users?page=2');
  try {
    console.log(await json());
   } catch (e) {
    console.log(e);
    console.log(json);
   }
}

[one, two, three, four, five].forEach(f => f());

再次感谢您的宝贵时间。

注意:出于某种原因,SO 将异常记录为空对象,因此这里是 fiddle:https://jsfiddle.net/ygbm6kwq/4/

编辑:不小心遗漏了示例二中的一行,片段和 fiddle 已更新。

The rest operator breaks it, which I do not understand. Is it making a new object and refusing to copy properties over?

是的,正是这样。 属性 rest 元素创建一个新对象并将任何剩余的可枚举 own 属性复制到其中。但是新的 r 将是一个普通对象,而不是 Response 实例 ,因此它不会继承 .json() 方法。

I was able to get the json method, but then it throws an illegal invocation exception when I try to execute it.

是的,这是一个方法。因此,必须在实例上调用它,并使用适当的 this 值。技术上你可以做到

const response = await fetch('https://reqres.in/api/users?page=2');
const { json } = response;
console.log(await json.call(response));

甚至没有解构,Response.prototype.json.call(response),但那没有意义。