1. JSはシングルスレッドであるのはなぜ?
ブラウザのスクリプト言語での主要な実行などjsが、主な目的JS操作DOMの一つです。
JSは、栗の上に標高で開催された2つのスレッドが動作するために、同じDOM上で同時に存在し、同じ時間にjsの場合、ブラウザは優先度を決定する方法を、どのようなスレッドに耳を傾ける必要がありますか?
この問題を回避するには、jsがシングルスレッドの言語でなければならず、将来的には、この機能は変更されません。
シングルスレッドの手段は、すべてのタスクは、ミッションの終了前に、後にタスクを実行し、ラインアップする必要があります。タスクは長い時間前にかかる場合は、その後のタスクが待っていました。
var i, t = Date.now()
for (i = 0; i < 100000000; i++) {}
console.log(Date.now() - t) // 238
この以上のように、キューは、CPUビジー計算集約的であるが、それがある場合にネットワーク要求が不適切な場合ので。ときにネットワーク要求リソースリターンが予測不可能であるため、このような状況は、ライン待ちで待機するように賢明だろう。
だから、同期と非同期があります。
2.同期および非同期
シンクロナス
同期タスクは、タスクは次のタスクに進む前に、タスクが終了する直前に、メインスレッド上で実行キューに入れられます。
// 同步代码
function fun1() {
console.log(1);
}
function fun2() {
console.log(2);
}
fun1();
fun2();
コードが実行されるので、出力は、上から下へ、順次入力1である。FUN1エンド()、それはfun2を継続します()。
非同期な
非同期タスクがタスクキューの使命に、メインスレッドを入力していない、タスクキューのみメインスレッドに通知し、非同期タスクを行うことができ、タスクは、メインスレッドを入力します。
function fun1() {
console.log(1);
}
function fun2() {
console.log(2);
}
function fun3() {
console.log(3);
}
fun1();
setTimeout(function(){
fun2();
},0);
fun3();
我々は、同期機能の実装を優先し、非同期機能の実装になりますので、順次、1,3,2を出力します。
JavaScriptがシングルスレッド、ノンブロッキング、実装が非同期のは簡単ですので、それは不確実性の動作時間のためにそうJavaScriptや時間のかかる操作で、ある非同期の使用が不可避な選択となりました。
JavaScriptの実行順序:
まず、同期、非同期1.
実行のために2非同期タスクキュー:最初のマイクロマイクロタスクタスクキュー、キューマクロタスクマクロタスク
決意の3コール約束は、マイクロ属するタスクキューを拒否し、setTimeoutメソッドに属するマクロタスクキューは、
前述されていますキュー、FIFO。
ミクロとマクロタスクタスクとは何ですか?
3.マクロおよびミクロタスクタスク
非同期タスクがマクロタスク(マクロタスク)マイクロタスク(マイクロタスク)に分割され、異なるタスクキューを入力するために、自身に対応するAPIを登録し、それらを順次実行スタックにプッシュ行うイベントループを待ちます。
マクロタスク
マクロタスク、コードスタックの各実行は、(各イベントのイベント・キューから、実行スタック実行にコールバックを取得含む)タスクを実行するマクロであることが理解されます。
順次実行されるように内部ブラウザJS(マクロ)タスクとDOMの作業を行うことができるようにするためには、ページの再レンダリングプロセスの開始前に実行マクロタスク次のマクロタスクの終了時に実行されます以下のとおりです。
macrotask->渲染->macrotask->...
マクロタスクは次のとおりです。
スクリプト(全体的なコード)
のsetTimeout
のsetInterval
I / O
UIのインタラクションイベント
のpostMessage
MessageChannel
setImmediate(Node.jsの環境)
マイクロタスク
マイクロタスク、タスクが現在のタスクの実行が終了した直後に行わことが理解されます。これは、レンダリングの前に、タスクの後に現在のタスク、次のタスクの前に、あります。
setTimeoutメソッドに比べて応答速度が(setTimeoutをタスクである)ので、レンダリングを待たずに、高速になりますので。これは、実行、特定のマクロタスクでは、すべてのマイクロタスクが実行中に生成されます、である(レンダリングする前に)完了しました。
マイクロタスクは次のとおりです。
Promise.then
Object.observe
MutaionObserver
process.nextTick(Node.jsの环境)
4.Eventループ(イベントループ)
次のようにイベントループ(イベントループ)、ダニと呼ばれる各サイクルは、各タスクをチェック:
行われた場合、最初のキューに入れられた実行スタックマクロタスク(通常は全スクリプトコード)を選択します。
マイクロタスク2.チェックし、もしマイクロタスク空のキューまで存在ストップの実行。
3.更新(ブラウザを更新するためにレンダリングすることができる、各イベントループ)をレンダリングします。
4.上記の手順を繰り返します。
マクロタスク]> [すべてのタスク]マイクロ>マクロタスク、以下のように:
コードの実行順序の観点から、同期タスクが発生し、コード実行のコードシーケンスに従ってプログラムを起動、実行直ちに;遭遇非同期タスクは、単に非同期要求を開始非同期関数を呼び出します。このとき、非同期タスクは、キューにメッセージキューが完了した後に行わ、非同期操作の実行を開始します。プログラムはコード順に従って終了した後、メッセージキュー内のメッセージ待ちがあるかどうかを確認してください。その場合、実行スタックへのメッセージから順に、メッセージキューが実行されます。機械加工後、メッセージキューから再取得メッセージは、次に実行が繰り返されます。
メインスレッドは、一定の繰り返しメッセージ、実行メッセージを取得し、そのメッセージを取り、そしてするため、次に実行されます。したがって、このメカニズムは、イベントループと呼ばれています。
彼はコードを表明しました:
while (queue.waitForMessage()) {
queue.processNextMessage();
}
あなたが現在どのニュースをお持ちでない場合はqueue.waitForMessageは、メッセージが到着同期を待ちます。
5.例
イベントループのメカニズムを説明するための例下:
console.log(1)
div.onclick = () => {console.log('click')}
console.log(2)
setTimeout(() => {console.log('timeout')},1000)
図1に示すように、最初の行、最初の行は、同期タスクである、ディスプレイコンソール
図2に示すように、2行目は、2行目は、マウスのクリックが非同期動作の任意の時点で行うことができる、非同期タスク非同期要求であります
3、三行目、三行目は、同期タスク、コンソール・ディスプレイである2
図4に示すように、第四のラインの実装では、4行目は1秒後にタイマータスクを実行するために、非同期タスク、非同期要求であります
5、それは四行目の実行から1秒を想定し、マウスクリックの実行は、マウスは、メッセージキューに最初のタスクにルーティングされます
6、第2のメッセージキューに四行目1sの実行、タイマータスクの後にルーティングされます
7.今すぐ同期タスクの実行に非同期タスクの実行スタックの順に、キューからメッセージを実行されました
8、コンソールは、順次「クリック」、「タイムアウト」を表示しました
9は、一定期間の後、彼らは、メッセージキューが空であるので、マウスがメッセージキューに最初のタスクにルーティングされ、マウスクリックを行いました
10、同期タスクは、非同期タスクの実行に実行スタックの順序でメッセージキューから、次に完了した後
11、コンソールディスプレイ「クリック」
非同期プロシージャ
完全な非同期プロセスを説明するための例下:
div.onclick = function fn(){console.log('click')}
1、非同期関数div.onclickを呼び出すことで、メインスレッド非同期要求
2、いくつかの点で、非同期操作を実行するために、すなわちマウスクリック
キューへの3、そして、FNコールバックメッセージキュー
図4に示すように、メインスレッドは、実行スタックFNへのメッセージキューから読み出されます
5、そして次に(「クリック」)実行スタック内にconsole.log FN内のコードを実行します
6、そして、コンソールディスプレイ「クリック」
例:何順次出力?
function fun1() {
console.log("1")
}
fun1()
setTimeout(function () {
console.log('2')
});
function fun3() {
console.log("3")
}
fun3()
var l4 = new Promise(function (resolve) {
for (var i = 0; i < 10000; i++) {
i == 99 && resolve();
}
}).then(function () {
console.log('4')
});
console.log('5');