获取 API - 它是阻塞代码还是非阻塞代码?
Fetch APIs - Is it blocking or non-blocking code?
我已经查看 Fetch API
几天了。
在学习过程中,我遇到了语句 "using fetch()
doesn't block your DOM ",因为它使用了承诺。
愉快地学习这些教程并查看一些新教程,我看到一个人在演示文稿中说 "using fetch()
does block your DOM"。
谁能教我这两个是哪一个?
在 blocking/non-blocking 代码的意义上使用 fetch
归结为同步代码和异步代码之间的区别。
JavaScript的一个设计范式叫做Run to Completion,它归结为这样一个事实,即当前正在执行的一段JS代码不能被另一段代码打断。换句话说,一个函数 运行s 直到它以同步方式完成(另请参阅最后的警告)。
当你有异步代码时,比如包裹在承诺中的代码(fetch
正在使用的代码),它会被安排到 运行 之后,在所有同步代码之后已完成 运行ning,以及所有其他先前计划的任务(microtasks for promises)。
这提供了一个时间间隔,允许 JS 在其中 运行ning 的系统的其他部分,例如浏览器中的 DOM,可以自由地在系统的某些部分上运行他们与 JavaScript 引擎共享,知道 JS 不会妨碍他们。
因此,从广义上讲,fetch
是非阻塞的,不会阻塞DOM。
需要注意的是,promises 表示通过异步调度链连接的同步代码块(例如the promise chain) so technically there are parts of fetch
that do block the DOM but the overall process can be considered non-blocking for most purposes. See 。
注意:在 ES6 中引入生成器后,函数不再是 JavaScript 中的原子执行单元。使用 yield
和之后的 await
,JS 函数能够分解为同步执行代码的多个异步块。
您可以这样使用提取 API:
fetch(url)
.then(function(data) {
// do something with the data fetched
})
.catch(function(error) {
// error handling
});
是的,this doesn't block your DOM. Yes, your code is asynchronous。
然而,这同样适用于具有 XMLHttpRequest
的旧式 XHR 请求:
var getJSON = function(url, successHandler, errorHandler) {
// 1. Make an Ajax call to your json file
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.onreadystatechange = function() {
var status, data;
if (xhr.readyState == 4) {
status = xhr.status;
if (status == 200) {
// 2. Parse the json file once it's been received
data = JSON.parse(xhr.responseText);
successHandler && successHandler(data);
} else {
errorHandler && errorHandler(status);
}
}
};
xhr.send();
};
getJSON('data.json', function(data) {
// 3. Do something with the content of the file once it's parsed
}, function(status) {
// Error handling goes here
});
fetch API 只为您提供更现代的 promise based API to do the same thing people used to do with XMLHttpRequest
and 。
因此,旧式 XMLHttpRequest
XHR 和 fetch API 都不会阻止您的 DOM。
我认为这家伙想说的是 fetch
本身正在阻塞。如同,创建 HTTP 请求并发送它所花费的时间是阻塞的,但是你的脚本和 UI 不会 在请求发出时被阻塞。您的 then()
回调也将被阻止。
也就是说,发送您的请求只需要五分之一毫秒,您无需担心。
> t=performance.now(),fetch('.'),(performance.now()-t)
0.139999999984866
如果您所说的阻止是指其他脚本和请求无法运行,直到其请求完成:否。
如果您的意思是阻止页面加载完成:是,它似乎会阻止。
这里有一些测试我做了一些比较来证明,要求搜索 google 的:what are dogs?
fetch()
似乎会阻止 window.onload
完成
https://jsfiddle.net/84uopaqb/7/
XMLHttpRequest
,不会阻止window.onload
完成
https://jsfiddle.net/84uopaqb/5/
$.get()
也 不会 阻止 window.onload
完成
https://jsfiddle.net/84uopaqb/1/
如果您必须使用 fetch,将 fetch
请求包装在 setTimeout
中是解决此问题的方法。
警告:
我只在 FF Quantum 中测试过这个,也不是很彻底……但话虽这么说,你应该支持所有主要浏览器。即使它在其他浏览器中是非阻塞的,它仍然不是一个可行的解决方案。
我已经查看 Fetch API
几天了。
在学习过程中,我遇到了语句 "using fetch()
doesn't block your DOM ",因为它使用了承诺。
愉快地学习这些教程并查看一些新教程,我看到一个人在演示文稿中说 "using fetch()
does block your DOM"。
谁能教我这两个是哪一个?
在 blocking/non-blocking 代码的意义上使用 fetch
归结为同步代码和异步代码之间的区别。
JavaScript的一个设计范式叫做Run to Completion,它归结为这样一个事实,即当前正在执行的一段JS代码不能被另一段代码打断。换句话说,一个函数 运行s 直到它以同步方式完成(另请参阅最后的警告)。
当你有异步代码时,比如包裹在承诺中的代码(fetch
正在使用的代码),它会被安排到 运行 之后,在所有同步代码之后已完成 运行ning,以及所有其他先前计划的任务(microtasks for promises)。
这提供了一个时间间隔,允许 JS 在其中 运行ning 的系统的其他部分,例如浏览器中的 DOM,可以自由地在系统的某些部分上运行他们与 JavaScript 引擎共享,知道 JS 不会妨碍他们。
因此,从广义上讲,fetch
是非阻塞的,不会阻塞DOM。
需要注意的是,promises 表示通过异步调度链连接的同步代码块(例如the promise chain) so technically there are parts of fetch
that do block the DOM but the overall process can be considered non-blocking for most purposes. See
注意:在 ES6 中引入生成器后,函数不再是 JavaScript 中的原子执行单元。使用 yield
和之后的 await
,JS 函数能够分解为同步执行代码的多个异步块。
您可以这样使用提取 API:
fetch(url)
.then(function(data) {
// do something with the data fetched
})
.catch(function(error) {
// error handling
});
是的,this doesn't block your DOM. Yes, your code is asynchronous。
然而,这同样适用于具有 XMLHttpRequest
的旧式 XHR 请求:
var getJSON = function(url, successHandler, errorHandler) {
// 1. Make an Ajax call to your json file
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.onreadystatechange = function() {
var status, data;
if (xhr.readyState == 4) {
status = xhr.status;
if (status == 200) {
// 2. Parse the json file once it's been received
data = JSON.parse(xhr.responseText);
successHandler && successHandler(data);
} else {
errorHandler && errorHandler(status);
}
}
};
xhr.send();
};
getJSON('data.json', function(data) {
// 3. Do something with the content of the file once it's parsed
}, function(status) {
// Error handling goes here
});
fetch API 只为您提供更现代的 promise based API to do the same thing people used to do with XMLHttpRequest
and
因此,旧式 XMLHttpRequest
XHR 和 fetch API 都不会阻止您的 DOM。
我认为这家伙想说的是 fetch
本身正在阻塞。如同,创建 HTTP 请求并发送它所花费的时间是阻塞的,但是你的脚本和 UI 不会 在请求发出时被阻塞。您的 then()
回调也将被阻止。
也就是说,发送您的请求只需要五分之一毫秒,您无需担心。
> t=performance.now(),fetch('.'),(performance.now()-t)
0.139999999984866
如果您所说的阻止是指其他脚本和请求无法运行,直到其请求完成:否。
如果您的意思是阻止页面加载完成:是,它似乎会阻止。
这里有一些测试我做了一些比较来证明,要求搜索 google 的:what are dogs?
fetch()
似乎会阻止 window.onload
完成
https://jsfiddle.net/84uopaqb/7/
XMLHttpRequest
,不会阻止window.onload
完成
https://jsfiddle.net/84uopaqb/5/
$.get()
也 不会 阻止 window.onload
完成
https://jsfiddle.net/84uopaqb/1/
如果您必须使用 fetch,将 fetch
请求包装在 setTimeout
中是解决此问题的方法。
警告: 我只在 FF Quantum 中测试过这个,也不是很彻底……但话虽这么说,你应该支持所有主要浏览器。即使它在其他浏览器中是非阻塞的,它仍然不是一个可行的解决方案。