JSはシングルスレッドです
次のコードを使用して、JSがシングルスレッドであることを証明できます。
<script type="text/javascript">
setTimeout(function () {
console.log('timeout 2222')
alert('22222222')
}, 2000)
setTimeout(function () {
console.log('timeout 1111')
alert('1111111')
}, 1000)
setTimeout(function () {
console.log('timeout() 00000')
}, 0)
function fn() {
console.log('fn()')
}
fn()
console.log('alert()之前')
alert('------') //暂停当前主线程的执行, 同时暂停计时, 点击确定后, 恢复程序执行和计时
console.log('alert()之后')
</script>
alert()関数には、現在のメインスレッドの実行を一時停止すると同時にタイミングを一時停止する機能があります
知っておくべき実行結果があり
ます。setTimeout()のコールバック関数はメインスレッドで実行され、タイマーコールバック関数は実行中のスタック内のすべてのコードが実行された後にのみ実行できます。
jsがマルチスレッドモードではなくシングルスレッドモードを使用するのはなぜですか?
JavaScriptのシングルスレッドはその目的に関連しています。ブラウザのスクリプト言語としてのJavaScriptの主な用途は、ユーザーとの対話とDOMの操作です。これにより、単一のスレッドのみである可能性があると判断されます。そうしないと、複雑な同期の問題が発生します。
たとえば、次のように想像できます。divで動作する2つのスレッドがあり、1つはスタイリングで、もう1つは削除です。スタイリングのためにスレッドの1つを実行しているときに、突然スレッドが切り替わり、divが削除され、元のスレッドに戻るときにエラーが発生する可能性がある状況があります。
別の観点からJSのコードを分類できます。
- 初期化コード
- コールバックコード
コードを実行するjsエンジンの基本的なプロセス:最初に初期化コードを実行します:いくつかの特別なコードを含みます->コールバック関数(非同期実行、コールバックコードは後で実行されます)
一般的なコールバック関数:
- タイマーを設定する
- バインドイベントリスナー
- ajaxリクエストを送信する
特別な注意:setTimeout()は初期化コードであり、その中のコールバック関数はコールバックコードです!
イベントループモデル
概略図:
WEB APISの3つのモジュールは、対応するコールバックコードの処理を担当します。この図から、3つのモジュールプロセッサ(ブラウザによって提供される)がサブスレッドの位置にあり、JSエンジンがメインスレッドの位置にあることがはっきりとわかります(これは、メインスレッド)
モデルの2つの重要なコンポーネント:
- イベント(タイマー/DOMイベント/Ajax)管理モジュール
- コールバックキュー
モデルの操作プロセス:
初期化コードを実行し、イベントコールバック関数を対応するモジュールに渡して管理します。イベントが発生すると、管理モジュールはコールバック関数とそのデータをコールバックキューに追加します。初期化コードが実行された後(一定の時間がかかる場合があります)にのみ、読み取りコールバックキューのコールバック関数がトラバースされて実行されます。 。
関連する概念:
- 実行スタック:すべてのコードはこのスペースで実行されます
- タスクキュー
- メッセージキュー
- イベントキュー
- 上記の3つのキューは、コールバックキュー(コールバックキュー)に相当します。
- イベントポーリング:タスクキューからコールバック関数を周期的に取り出し、処理のために実行スタックに入れます(1つずつ)
この時点で、スレッドメカニズムとイベントメカニズム①でタイマーが不正確である理由を説明できます。私たちの時間を本当に助けてくれるのは、setTimeoutコールバック処理モジュールです。JSエンジンは私たちの時間を助けません。時間切れになった後、すぐに実行することを意味するものではありません!代わりに、モジュールはコールバック関数をコールバックキューに入れます。コールバックキューは、この時点で実行を待機している状態です。実行スタック内のコードが実行された後でのみ、コールバックキュー内のコードが実行スタックに配置されて実行されます。スタック内の初期化コードの実行に時間がかかりすぎると、コールバックコードが実行スタックに遅れて入るため、タイミングが不正確であるように見えます。
H5Webワーカーはマルチスレッドを実装します
Web Workersは、HTML5が提供するjavascriptマルチスレッドソリューションです。ユーザーインターフェイスをフリーズすることなく、計算量の多いコードをWebワーカーに実行できます。ただし、子スレッドはメインスレッドによって完全に制御されます。DOMを操作してはいけません。したがって、この新しい標準はJavaScriptのシングルスレッドの性質を変更しません
使用手順:
- 別のスレッドで実行されるjsファイルを作成します
- メッセージを送信し、メインスレッドのjsでコールバックを設定します
関連するAPI
- ワーカー:コンストラクター、スレッドによって実行されるjsファイルをロードします
- Worker.prototype.onmessage:別のスレッドを受信するためのコールバック関数
- Worker.prototype.postMessage:別のスレッドにメッセージを送信します
シナリオをシミュレートします。サブスレッドを使用してフィボナッチ数列を計算し、計算期間中にユーザーインターフェイスをフリーズせず、自由に操作できます。
メインスレッド:
<input type="text" placeholder="数值" id="number">
<button id="btn">计算</button>
<script type="text/javascript">
var input = document.getElementById('number')
document.getElementById('btn').onclick = function () {
var number = input.value
//创建一个Worker对象
var worker = new Worker('worker.js')
// 绑定接收消息的监听
worker.onmessage = function (event) {
console.log('主线程接收分线程返回的数据: '+event.data)
alert(event.data)
}
// 向分线程发送消息
worker.postMessage(number)
console.log('主线程向分线程发送数据: '+number)
}
// console.log(this) // window
</script>
サブスレッド:
function fibonacci(n) {
return n<=2 ? 1 : fibonacci(n-1) + fibonacci(n-2) //递归调用
}
console.log(this)
this.onmessage = function (event) {
var number = event.data
console.log('分线程接收到主线程发送的数据: '+number)
//计算
var result = fibonacci(number)
postMessage(result)
console.log('分线程向主线程返回数据: '+result)
// alert(result) alert是window的方法, 在分线程不能调用
// 分线程中的全局对象不再是window, 所以在分线程中不可能更新界面
//console是每个浏览器都提供的实现,跟window没有关系
}
知らせ:
- alertはウィンドウのメソッドであり、サブスレッドでは呼び出すことができません
- サブスレッドのグローバルオブジェクトはウィンドウではなくなったため、サブスレッドのインターフェイスを更新することはできません
- コンソールはすべてのブラウザによって提供される実装であり、ウィンドウとは何の関係もありません
グラフィック:
不十分:
- ドメイン間でJSを読み込めません
- ワーカーのコードがDOMにアクセスできません(UIを更新します)
- すべてのブラウザがこの新機能をサポートしているわけではありません