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代碼是單線程的鹿霸,同一時間只有一段代碼在執(zhí)行蒂胞。但是拆撼,js運行環(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(當異步任務完成后署隘,回調函數(shù)才會被放到任務隊列中殷勘。而注冊回調函數(shù)時况鸣,并不會把回調放到任務隊列中。). 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(異步任務執(zhí)行完后的回調已經在任務隊列中了饵较,但是主線程不執(zhí)行完,就不會從任務隊列中取回調遭赂,該回調前的回調沒有執(zhí)行完循诉,也不會取這個回調。). 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(從隊列先取出一個執(zhí)行完再绕菜), 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
是異步任務茄猫,
所以不等帶執(zhí)行完狈蚤,就立即執(zhí)行主線程的xhr.addEventListener
以及后面的代碼。
等異步任務執(zhí)行完划纽,listener會放到任務隊列中脆侮。
主線程執(zhí)行完后,會從任務隊列中取回調函數(shù)勇劣,
當取到listener時靖避,這個回調就觸發(fā)了。
但是比默,如果改成一下方式幻捏,就不能觸發(fā)回調了。
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響應完,發(fā)現(xiàn)并沒有注冊回調醋奠,就不會把回調放到任務隊列中榛臼。
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);
執(zhí)行順序:1 2 3 0
我們看到,
<u></u>new Promise
的參數(shù)是同步函數(shù)例证,會立即執(zhí)行路呜,才會執(zhí)行后面的alert(2)
<u></u>p.then
在Promise resolve后仍然可以注冊,并立即放到任務隊列中织咧。
<u></u>p.then
注冊的回調是異步的胀葱,放到任務隊列但是不會馬上執(zhí)行,等主線程執(zhí)行完才執(zhí)行笙蒙。