为啥对 fetch 响应使用解构赋值会导致 .json() 方法消失?
Posted
技术标签:
【中文标题】为啥对 fetch 响应使用解构赋值会导致 .json() 方法消失?【英文标题】:Why does using a destructuring assignment on a fetch response cause the .json() method to disappear?为什么对 fetch 响应使用解构赋值会导致 .json() 方法消失? 【发布时间】:2019-07-15 23:16:37 【问题描述】:感谢您抽出宝贵时间查看此内容。我遇到了一些意外的行为,在使用 aws lambda 时我无法弄清楚。
我正在执行 fetch,然后根据它是成功还是失败来做一些不同的事情,如果一切都是 kosher,最终我想使用 fetch.json() 方法。我正在使用 await 使我的 lambda 处理程序的内部“同步”。
当我将获取的结果分配给一个变量然后检查它时,一切都很好。但是我喜欢整洁的代码,所以我决定使用解构赋值,突然事情就开始崩溃了。
为了证明我的困惑,我包含了一个代码 sn-p,它复制了问题并显示了五种不同的东西 - 前两个有效,其余的中断。
在第三个例子中,“r”是一个空对象。其余操作员打破了它,我不明白。它是在制作一个新对象并拒绝复制属性吗?解构发生时属性不存在吗?如果是这样,为什么 ok 和 status 会正确解构?
四只是三问题的简化示例。
Five也让我很困惑,因为我能够得到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 将异常记录为空对象,所以这里有一个小提琴:https://jsfiddle.net/ygbm6kwq/4/
编辑:在示例二中意外遗漏了一行,更新了 sn-p 和 fiddle。
【问题讨论】:
I'm using await to make the interior of my lambda handler "synchronous."
await 不会使代码同步。 [one, two, three, four, five].forEach
在这里你循环了 5 个 promise,而不是 5 个 promise 的结果。
@LucaKiebel 我正在使用扩展运算符。
@Keith 这就是我将“同步”放在引号中的原因。我知道它实际上不是同步的。我试图挥手与问题无关的东西。很抱歉有任何混淆。
(当 sn-p 控制台未准确显示信息时,您可以建议问题查看者改为查看他们实际的浏览器控制台 - 尽管 sn-p 运行在另一个域)
请注意,在您的第一个示例中,如果您运行r instanceof Response
,您将得到true
。如果您使用扩展运算符,情况就不会如此。因为扩展运算符相当于这样做:Object.assign(, r)
。而在Object.assign
的第一个参数中的那个空对象不是Response
的实例
【参考方案1】:
其余运算符打破了它,我不明白。它是在创建一个新对象并拒绝复制属性吗?
是的,正是如此。属性 rest 元素创建一个新对象并将所有剩余的可枚举 own 属性复制到其中。但是新的r
将是一个普通对象,而不是Response
实例,因此它不会继承.json()
方法。
我能够获取json方法,但是当我尝试执行它时它会抛出一个非法调用异常。
是的,这是一个方法。因此,必须在实例上调用它,并使用正确的 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)
,但这没有意义。
【讨论】:
99% 的路程。 json 不是可枚举属性,因为它是响应原型链的一部分吗? @JSager 问题不在于可枚举性(我不知道它们是否可枚举,我只是猜想它们不是),而是.json
是一个继承的 财产。
好的,谢谢。我在那里有一些阅读要做,但这澄清了这个谜。我知道我快到了,但“为什么”的最后一步让我望而却步。这就是我从不写课程的原因:)以上是关于为啥对 fetch 响应使用解构赋值会导致 .json() 方法消失?的主要内容,如果未能解决你的问题,请参考以下文章
使用对象解构赋值时,为啥将属性“名称”转换为字符串? [复制]