[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代碼是單線程的,同一時(shí)間只有一段代碼在執(zhí)行。但是,js運(yùn)行環(huán)境不是單線程的) 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(當(dāng)異步任務(wù)完成后,回調(diào)函數(shù)才會(huì)被放到任務(wù)隊(duì)列中。而注冊(cè)回調(diào)函數(shù)時(shí),并不會(huì)把回調(diào)放到任務(wù)隊(duì)列中。). 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(異步任務(wù)執(zhí)行完后的回調(diào)已經(jīng)在任務(wù)隊(duì)列中了,但是主線程不執(zhí)行完,就不會(huì)從任務(wù)隊(duì)列中取回調(diào),該回調(diào)前的回調(diào)沒有執(zhí)行完,也不會(huì)取這個(gè)回調(diào)。). 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(從隊(duì)列先取出一個(gè)執(zhí)行完再?。?/strong>, running the code that the item triggers, and then checking the queue again. This cycleis known as the event loop.

注:關(guān)于XMLHttpRequest與Promise

(1)XMLHttpRequest

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

xhr.addEventListener('load', listener);

因?yàn)?code>xhr.send是異步任務(wù),
所以不等帶執(zhí)行完,就立即執(zhí)行主線程的xhr.addEventListener以及后面的代碼。
等異步任務(wù)執(zhí)行完,listener會(huì)放到任務(wù)隊(duì)列中。
主線程執(zhí)行完后,會(huì)從任務(wù)隊(duì)列中取回調(diào)函數(shù),
當(dāng)取到listener時(shí),這個(gè)回調(diào)就觸發(fā)了。

但是,如果改成一下方式,就不能觸發(fā)回調(diào)了。

var async = true;
var xhr = new XMLHttpRequest();
xhr.open('get', 'data.json', async);
xhr.send();    //假設(shè)ajax 5s內(nèi)一定會(huì)返回。

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

等ajax響應(yīng)完再addEventListener是沒有用的,
因?yàn)閍jax響應(yīng)完,發(fā)現(xiàn)并沒有注冊(cè)回調(diào),就不會(huì)把回調(diào)放到任務(wù)隊(duì)列中。
5000后注冊(cè)的回調(diào),只有在下次send時(shí),才會(huì)用到。

(2)Promise

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

alert(2);

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

alert(3);
執(zhí)行順序:1 2 3 0

我們看到,
<u></u>new Promise的參數(shù)是同步函數(shù),會(huì)立即執(zhí)行,才會(huì)執(zhí)行后面的alert(2)
<u></u>p.then在Promise resolve后仍然可以注冊(cè),并立即放到任務(wù)隊(duì)列中。
<u></u>p.then注冊(cè)的回調(diào)是異步的,放到任務(wù)隊(duì)列但是不會(huì)馬上執(zhí)行,等主線程執(zhí)行完才執(zhí)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容