为啥 Body.json() 返回一个 Promise? [复制]

Posted

技术标签:

【中文标题】为啥 Body.json() 返回一个 Promise? [复制]【英文标题】:Why does Body.json() return a Promise? [duplicate]为什么 Body.json() 返回一个 Promise? [复制] 【发布时间】:2018-06-01 15:11:37 【问题描述】:

我从 JS 开始,实际上喜欢异步方面(来自 Python),但我不确定为什么有些函数会返回 Promise。具体来说,下面使用fetch的代码让我想知道json()返回了什么:

fetch('https://freegeoip.net/json/8.8.8.8')
  .then((response) => 
    return response.json()
  )
  .then((json) => 
    Object.keys(json).forEach((key) => 
      console.log("got " + key)
    )
  )

抛开流式传输不谈,我们在GET 之后得到的 HTTP 响应是一个文本块,随后客户端会对其进行解释以提取标题、正文和其他有趣的元素 - 作为 HTTP 内容分析的一部分。

重点是这段文字是一体的,所以第一个then()已经有了完整的响应——为什么解析JSON体是一个异步操作,和第二个@中的forEach不同987654327@?

换句话说,为什么我不能让下面的代码工作?

fetch('https://freegeoip.net/json/8.8.8.8')
  .then((response) => 
    Object.keys(response.json()).forEach((key) => 
      console.log("got " + key)
    )
  )

注意:如果第一个代码运行不正确(使用ERR_BLOCKED_BY_CLIENT),请尝试禁用您的广告拦截器。第二个是故意不正确的。

【问题讨论】:

"我们在 GET 之后得到的 HTTP 响应是一个文本块" - 不。这是一个流。 @Bergi:在这种情况下,一切都是流(数据包、字节等)。 GET 将一个已完成的文本块合并为一个片段(除了真正的流式传输,数据流不会结束)。同样,不能谈论“将文件读入内存”,因为它在技术上是流式传输。 流式传输的要点在于它可以带来多个文本块——例如,可以在正文尚未完成时已经处理标题。这正是这里发生的事情。 【参考方案1】:

您的第二个 sn-p 不起作用,因为 response.json() aka body.json() 不会立即解决。

这是因为 body.JSON() streamsreturnsResponse 异步使用了 Promise;然后必须由then() 回调捕获,以便读取/操作。

这就是Promises的本质。

然而,这样的句法流仍然可以通过利用asyncawait来实现。

fetch('https://freegeoip.net/json/8.8.8.8')
.then(async (response) => 
  Object.keys(await response.json()).forEach((key) => 
    console.log("got " + key)
  )
)

【讨论】:

【参考方案2】:

你是对的 - 两个 sn-ps 都做同样的事情。在第一个 sn-p 中,以下部分:

.then((response) => 
  return response.json()
)

只是在第一步中处理响应并传递结果。这个简单的案例不需要分成两个步骤,所以你可以很容易地使用第二个例子。

在某些情况下它可能很有用。

【讨论】:

以上是关于为啥 Body.json() 返回一个 Promise? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

http协议发送header+body+json及接收解析

使用body.json()解析来自http.get()的响应时出错

在 AngularJs 中清除服务数据

简单理解JavaScript 的async/await

asyncawait与Promise

koa路由接口