[JavaScript] Run to Completion and the Event Loop

The JavaScript you write runs on a single thread, which avoids complications found in otherlanguages that share memory between threads. But if JavaScript is single-threaded, where are theasync tasks and callbacks run?

youwere just told that JavaScript is single-threaded. Here’s the distinction: the JavaScript code you write(js代码是单线程的,同一时间只有一段代码在执行。但是,js运行环境不是单线程的) all runs on a single thread, but the code that implements the async tasksis not part of that JavaScript and is free to runin a separate thread.

Once the task completes the result needs to be provided to the JavaScript thread. At this point the callback is placed in a queue(当异步任务完成后,回调函数才会被放到任务队列中。而注册回调函数时,并不会把回调放到任务队列中。). A multithreaded language might interrupt whatever code was
currently executing to provide the results, but in JavaScript these interruptions are forbidden.Instead there is a run-to-completion rule, which means that your code runs without interruptionuntil it passes control back to the host environment by returning from the function that the hostinitially called. At that point the callback can be removed from the queue and invoked.

All other threads communicate with your code by placing items on the queue. They are not
permitted to manipulate any other memory accessible to JavaScript.

After the callback is added to the queue, there is no guarantee how long it will have to wait(异步任务执行完后的回调已经在任务队列中了,但是主线程不执行完,就不会从任务队列中取回调,该回调前的回调没有执行完,也不会取这个回调。). Howlong it takes the current code to run to completion and what else is in the queue controls the time.The queue can contain things such as mouse clicks, keystrokes, and callbacks for other async tasks.The JavaScript runtime simply continues in an endless cycle of pulling an item off the queue if one is available(从队列先取出一个执行完再取), running the code that the item triggers, and then checking the queue again. This cycleis known as the event loop.

注:关于XMLHttpRequest与Promise

(1)XMLHttpRequest

var async = true;
var xhr = new XMLHttpRequest();
xhr.open('get', 'data.json', async);
xhr.send();

xhr.addEventListener('load', listener);

因为xhr.send是异步任务,
所以不等带执行完,就立即执行主线程的xhr.addEventListener以及后面的代码。
等异步任务执行完,listener会放到任务队列中。
主线程执行完后,会从任务队列中取回调函数,
当取到listener时,这个回调就触发了。

但是,如果改成一下方式,就不能触发回调了。

var async = true;
var xhr = new XMLHttpRequest();
xhr.open('get', 'data.json', async);
xhr.send();    //假设ajax 5s内一定会返回。

setTimeout(function(){
    xhr.addEventListener('load', listener);
},5000);

等ajax响应完再addEventListener是没有用的,
因为ajax响应完,发现并没有注册回调,就不会把回调放到任务队列中。
5000后注册的回调,只有在下次send时,才会用到。

(2)Promise

var p=new Promise(function(resolve,reject){
    alert(1);
    resolve(0);
});

alert(2);

p.then(function(v){
    alert(v); //0
});

alert(3);
执行顺序:1 2 3 0

我们看到,
new Promise的参数是同步函数,会立即执行,才会执行后面的alert(2)
p.then在Promise resolve后仍然可以注册,并立即放到任务队列中。
p.then注册的回调是异步的,放到任务队列但是不会马上执行,等主线程执行完才执行。

你可能感兴趣的:([JavaScript] Run to Completion and the Event Loop)