简体   繁体   English

获取 API - 它是阻塞代码还是非阻塞代码?

[英]Fetch APIs - Is it blocking or non-blocking code?

I've been looking at the Fetch API for a couple of days now.几天来我一直在研究Fetch API

While learning I came across the statement "using fetch() doesn't block your DOM " as it uses promises.在学习的过程中,我遇到了“使用fetch()不会阻止你的 DOM”这句话,因为它使用了 promises。

Happily moving forward with these tutorials and checking out some new ones, I saw a guy stating "using fetch() does block your DOM" in a presentation.愉快地继续学习这些教程并查看一些新教程,我看到一个人在演示文稿中说“使用fetch()确实会阻止您的 DOM”

Can anyone educate me which one of the two it is?谁能教我这是两个中的哪一个?

Using fetch in the sense of blocking/non-blocking code comes down to the difference between synchronous and asynchronous code.在阻塞/非阻塞代码的意义上使用fetch归结为同步代码和异步代码之间的区别。

One of JavaScript's design paradigms is called Run to Completion and it boils down to the fact that a piece of JS code that is currently executing cannot be interrupted by another piece of code. JavaScript 的一种设计范式称为Run to Completion ,它归结为这样一个事实,即当前正在执行的一段 JS 代码不能被另一段代码打断。 In other words, a function runs until it's finished, in a synchronous manner (also see the caveat in the end).换句话说,一个函数以同步方式运行直到它完成(另请参阅最后的警告)。

When you have code that is asynchronous, such as the one wrapped in a promise (which is what fetch is using), it gets scheduled to run later, after all the synchronous code is finished running, as well as after all other previously scheduled tasks ( microtasks for promises).当你有异步代码时,比如包裹在承诺中的代码( fetch正在使用的代码),它会被安排在稍后运行,在所有同步代码完成运行之后,以及在所有其他先前计划的任务之后( 承诺的微任务)。

This provides a gap in time that allows other parts of the system within which JS is running, such as the DOM in the browser, to freely operate on parts of the system that they share with the JavaScript engine, knowing JS won't get in their way.这提供了一个时间间隙,允许运行 JS 的系统的其他部分,例如浏览器中的 DOM,可以自由地操作它们与 JavaScript 引擎共享的系统部分,知道 JS 不会进入他们的路。

Therefore, in the broadest sense, fetch is non-blocking and doesn't block the DOM.因此,从广义上讲, fetch是非阻塞的,不会阻塞 DOM。

It should be noted that promises represent synchronous code blocks connected via an asynchronous scheduling chain ( 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.应该注意的是,promises 表示通过异步调度链( promise 链)连接的同步代码块,因此从技术上讲, fetch的某些部分确实会阻塞 DOM,但对于大多数目的而言,整个过程可以被认为是非阻塞的。 See the answer by mpen for an example.有关示例,请参见mpen 的答案


Note: after generators were introduced in ES6, a function stopped being the atomic execution unit in JavaScript.注意:在 ES6 中引入生成器后,函数不再是 JavaScript 中的原子执行单元。 With yield and afterwards await , JS functions got the ability to break up into multiple async chunks of synchronously executing code.通过yield和之后的await ,JS 函数能够分解为多个同步执行代码的异步块。

I think what the guy was trying to say is that fetch itself is blocking.我认为这个人想说的是fetch本身正在阻塞。 As in, the time it takes to create an HTTP request and send it is blocking, but your script and UI won't be blocked while the request is out and about.如同,创建 HTTP 请求并发送它所花费的时间是阻塞的,但是当请求发出时您的脚本和 UI不会被阻塞。 Your then() callback will also be blocking.您的then()回调也将被阻塞。

That said, it only takes like a 5th of a millisecond to send your request, it's nothing you need to worry about.也就是说,发送您的请求只需要五分之一毫秒,您无需担心。

> t=performance.now(),fetch('.'),(performance.now()-t)
0.139999999984866

If by blocking you mean, other scripts and requests cannot run until its request completes: no .如果您的意思是阻止,则其他脚本和请求在其请求完成之前无法运行:

If you mean preventing the page load from completing: yes , it appears to block.如果您的意思是阻止页面加载完成:的,它似乎会阻止。

Here are some tests I made some to compare to demonstrate, requesting a search to google of: what are dogs?这里有一些我做的一些测试来比较演示,请求搜索到谷歌:什么是狗?

fetch() which does appear to block window.onload completion https://jsfiddle.net/84uopaqb/7/ fetch()确实会阻止window.onload完成https://jsfiddle.net/84uopaqb/7/

XMLHttpRequest , which does not block window.onload completion https://jsfiddle.net/84uopaqb/5/ XMLHttpRequest ,它不会阻止window.onload完成https://jsfiddle.net/84uopaqb/5/

$.get() which also does not block window.onload completion https://jsfiddle.net/84uopaqb/1/ $.get()不会阻止window.onload完成https://jsfiddle.net/84uopaqb/1/

If you must use fetch, wrapping the fetch request in a setTimeout is a workaround to this issue.如果您必须使用 fetch,将fetch请求包装在setTimeout中是解决此问题的一种方法。

Caveat : I've only tested this in FF Quantum, and not very thoroughly either... but that being said, you should support all major browsers.警告:我只在 FF Quantum 中测试过这个,也不是很彻底……但话虽这么说,你应该支持所有主要浏览器。 Even if it's non-blocking in other browsers, its still not a viable solution.即使它在其他浏览器中是非阻塞的,它仍然不是一个可行的解决方案。

You use the fetch API like this:您可以像这样使用 fetch API:

fetch(url)
.then(function(data) {
    // do something with the data fetched
})
.catch(function(error) {
    // error handling
});

Yes, this doesn't block your DOM .是的, 这不会阻止您的 DOM Yes, your code is asynchronous .是的, 你的代码是异步的

However, the same applies to oldschool XHR requests with XMLHttpRequest :然而,这同样适用于使用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
});

The fetch API just provides you a more modern promise based API to do the same thing people used to do with XMLHttpRequest and callbacks . fetch API 只是为您提供了一个更现代的基于promise的 API 来做人们过去使用XMLHttpRequestcallbacks做的同样的事情。

So, both oldschool XMLHttpRequest XHR and the fetch API do NOT block your DOM.所以,老派的XMLHttpRequest XHR 和 fetch API 都不会阻止你的 DOM。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM