Javascript 为什么这些获取方法是异步的?
Fetch是用于发出网络请求的基于Promise的新API:Javascript 为什么这些获取方法是异步的?,javascript,fetch,Javascript,Fetch,Fetch是用于发出网络请求的基于Promise的新API: fetch('https://www.everythingisawesome.com/') .then(response => console.log('status: ', response.status)); 这对我来说是有意义的——当我们发起一个网络呼叫时,我们会返回一个承诺,让我们的线程继续处理其他业务。当响应可用时,承诺中的代码将执行 但是,如果我对响应的有效负载感兴趣,我会通过响应的方法而不是属性来实现: a
fetch('https://www.everythingisawesome.com/')
.then(response => console.log('status: ', response.status));
这对我来说是有意义的——当我们发起一个网络呼叫时,我们会返回一个承诺,让我们的线程继续处理其他业务。当响应可用时,承诺中的代码将执行
但是,如果我对响应的有效负载感兴趣,我会通过响应的方法而不是属性来实现:
- arrayBuffer()
- blob()
- formData()
- json()
- 正文()
fetch('https://www.everythingisawesome.com/') //IO bound
.then(response => response.json()); //We now have the response, so this operation is CPU bound - isn't it?
.then(entity => console.log(entity.name));
为什么处理响应的有效负载会返回一个承诺-我不清楚为什么它应该是一个异步操作。,因为在您开始阅读内容之前,内容不会被传输。头首先出现。查看实现获取
json
的操作是CPU限制的,因为响应承诺完成后,响应以及主体的创建就完成了。请参阅
话虽如此,我认为这主要是一个设计概念,因此您可以链接承诺处理程序,并且只使用一个启动的错误处理程序,无论错误发生在哪个阶段
像这样:
fetch('https://www.everythingisawesome.com/')
.then(function(response) {
return response.json()
})
.then(function(json) {
console.log('parsed json', json)
})
.catch(function(ex) {
console.log('parsing or loading failed', ex)
})
已经解决的承诺的创建是以相当低的开销实现的。最后,这里不需要使用承诺,但它可以使代码更美观,并且可以编写。至少在我看来。在阅读了fetch的实现之后,使用承诺似乎有几个原因。对于初学者来说,
json()
依赖于FileReader
将响应blob转换为文本<在onload
回调之前,无法使用code>FileReaders,因此承诺链就是从这里开始的
function fileReaderReady(reader) {
return new Promise(function(resolve, reject) {
reader.onload = function() {
resolve(reader.result)
}
reader.onerror = function() {
reject(reader.error)
}
})
}
在此基础上,使用额外的承诺来封装可能发生的特定错误,并将其传播给调用方。例如,如果之前已经读取过一次主体,如果blob没有转换为文本,如果文本没有转换为JSON,则可能会发生错误。承诺在这里是方便的,因为这些不同的错误中的任何一个都将简单地结束在调用方的catch块中
综上所述,基于承诺的api用于读取fetch响应,因为:
1.它们依赖于文件读取器
,该读取器必须异步初始化自身。
2.fetch希望传播在读取正文时可能发生的各种错误。承诺允许以统一的方式实现这一点
为什么这些获取方法是异步的
天真的答案是
- 调用
方法时,必须返回使用arrayBuffer运行的结果arrayBuffer()
- 调用
方法时,必须返回使用blob运行的结果blob()
- 调用
方法时,必须返回使用formData运行的结果formData()
- 调用
方法时,必须返回使用json运行的结果json()
- 调用
方法时,必须返回使用文本运行的结果text()
当您使用fetch API从资源请求数据时,您必须等待资源完成下载,然后才能使用它。这应该是相当明显的。JavaScript使用异步API来处理此行为,以便所涉及的工作不会阻止其他脚本,更重要的是,不会阻止UI 资源下载完成后,数据可能会非常庞大。没有任何东西可以阻止您请求超过50MB的单一JSON对象 如果试图同步解析50MB的JSON,您认为会发生什么?它将阻止其他脚本,更重要的是阻止UI 其他程序员已经解决了如何以高效的方式处理大量数据:流。在JavaScript中,流是使用异步API实现的,这样它们就不会阻塞,如果您阅读了详细信息,那么很明显流是用来解析数据的: 若body为非null,则将stream设为body的流,否则设为空的ReadableStream对象 现在,规范可能已经定义了两种访问数据的方法:一种是用于较小数据量的同步API,另一种是用于较大数据量的异步API,但这会导致混淆和重复
此外。可以用同步代码表示的所有内容都可以用异步代码表示。事实并非如此。因此,创建了一个可以处理所有用例的异步API。不要相信这是真的。如果省略除初始提取之外的所有内容-
fetch('http://localhost:22898/api/values');代码>-我仍然可以通过电线获得有效载荷。响应头和负载不是逐段传递的。这取决于请求。如果发出head请求,则根本不会得到有效负载。假设您正在请求一个大文件。标题首先返回内容的详细信息。在建立tls级别等方面也可能有很多来回。看看底层的http协议。嗯,在协调跨源请求时,听起来也与选项相关。因此,如果fetch操作由HEAD和GET组成,那么我在这里读的是哪些响应头:。然后(response=>printOut(response.headers))
?cod