Async Hooks は Node8 の新機能です。NodeJs の非同期リソースのライフサイクルを追跡するための API をいくつか提供します。これは NodeJs の組み込みモジュールであり、直接参照できます。 定数 async_hooks = require('async_hooks'); これはめったに使用されないモジュールですが、なぜ存在するのでしょうか? ご存知のとおり、JavaScript は最初からシングルスレッド言語として設計されています。これは、JavaScript の元々の設計意図に関係しています。元々の JavaScript は、ネットワーク速度が低かった時代に、ユーザーがサーバーの応答を待つ時間コストを削減するために、ページ上のフォーム検証を実行するためにのみ使用されていました。 Web フロントエンド技術の発展に伴い、フロントエンド機能はますます強力になり、ますます重要になっていますが、シングルスレッドで解決できない問題はないようです。比較すると、マルチスレッドはより複雑であるように思われるため、現在でもシングルスレッドが使用されています。 JavaScript はシングルスレッドなので、日常の開発ではタイマーや現在標準化されている Ajax など、時間のかかるタスクが常に存在します。これらの問題を解決するために、JavaScript は BOM、DOM、ECMAScript に分かれています。BOM は、非同期タスクと呼ばれる時間のかかるタスクを解決するのに役立ちます。 ブラウザの BOM は非同期タスクの処理に役立つため、ほとんどのプログラマーは非同期タスクの使用方法以外についてほとんど何も知りません。たとえば、同時にキューにある非同期タスクの数はいくつでしょうか?非同期処理が混雑しているかどうかなどの関連情報を直接取得する方法はありません。多くの場合、基盤となるレイヤーでは関連情報に注意を払う必要はありません。ただし、場合によっては関連情報が必要な場合に備えて、NodeJS では async_hooks という実験的な API が提供されています。なぜ NodeJS か? タイマーや http などの非同期モジュールを開発者が制御できるのは Node だけだからです。ブラウザーが対応する API を提供しない限り、ブラウザーの BOM は開発者によって制御されません。 async_hooksルールasync_hooks は、各関数がコンテキスト (非同期スコープと呼ばれる) を提供することを規定しています。各非同期スコープには、現在の非同期スコープのロゴである asyncId があります。同じ非同期スコープ内の asyncId は同じである必要があります。 複数の非同期タスクが並行して実行されている場合、asyncId を使用すると、どの非同期タスクを監視するかを区別できます。 asyncId は、自己増加する非反復の正の整数です。プログラムの最初の asyncId は 1 である必要があります。 簡単に言うと、async スコープは中断できない同期タスクです。中断できない限り、コードがどれだけ長くても asyncId を共有します。ただし、途中でコールバックや await など中断できる場合は、新しい非同期コンテキストが作成され、新しい asyncId が作成されます。 各非同期スコープには、現在の関数がその非同期スコープによってトリガーされることを示す triggerAsyncId があります。 asyncId と triggerAsyncId を使用すると、非同期呼び出しの関係とリンク全体を簡単に追跡できます。 async_hooks.executionAsyncId() は asyncId を取得するために使用されます。グローバル asyncId が 1 であることがわかります。 async_hooks.triggerAsyncId() は triggerAsyncId を取得するために使用され、その現在の値は 0 です。 定数 async_hooks = require('async_hooks'); console.log('asyncId:', async_hooks.executionAsyncId()); // asyncId: 1 console.log('triggerAsyncId:', async_hooks.triggerAsyncId()); // トリガーAsyncId: 0 ここでは、 fs.open を使用してファイルを開きます。 fs.open の asyncId は 7 で、 fs.open の triggerAsyncId は 1 になることがわかります。これは、 fs.open がグローバル呼び出しによってトリガーされ、グローバル asyncId が 1 であるためです。 定数 async_hooks = require('async_hooks'); console.log('asyncId:', async_hooks.executionAsyncId()); // asyncId: 1 console.log('triggerAsyncId:', async_hooks.triggerAsyncId()); // トリガーAsyncId: 0 定数 fs = require('fs'); fs.open('./test.js', 'r', (err, fd) => { console.log('fs.open.asyncId:', async_hooks.executionAsyncId()); // 7 console.log('fs.open.triggerAsyncId:', async_hooks.triggerAsyncId()); // 1 }); 非同期関数のライフサイクルもちろん、実際のアプリケーションでは async_hooks はこのようには使用されません。正しい使用方法は、すべての非同期タスクが作成、実行、破棄される前、後、および後にコールバックをトリガーし、すべてのコールバックが asyncId で渡されることです。 async_hooks.createHook を使用して、非同期リソース フックを作成できます。このフックは、オブジェクトをパラメーターとして受け取り、非同期リソースのライフ サイクルで発生する可能性のあるイベントのコールバック関数を登録します。これらのフック関数は、非同期リソースが作成/実行/破棄されるたびにトリガーされます。 定数 async_hooks = require('async_hooks'); 定数asyncHook = async_hooks.createHook({ init(asyncId, type, triggerAsyncId, resource) { }, 破棄(非同期ID) { } }) 現在、createHook 関数は次の 5 種類のフック コールバックを受け入れることができます。 1. init(asyncId、type、triggerAsyncId、resource)
async_hooks.createHook 関数を使用して、各非同期リソースのライフサイクルで発生する init/before/after/destory/promiseResolve やその他の関連イベントのリスナー関数を登録できます。 2. 前(非同期ID) before 関数は、通常、asyncId に対応する非同期リソース操作が完了した後、コールバックが実行される前に呼び出されます。before コールバック関数は、コールバックされる回数によって複数回実行される場合があります。使用時にはこの点に注意してください。 3.after(非同期ID) after コールバック関数は通常、非同期リソースがコールバック関数を実行した直後に呼び出されます。コールバック関数の実行中にキャッチされない例外が発生した場合は、「uncaughtException」イベントがトリガーされた後に after イベントが呼び出されます。 4.破棄(非同期ID) asyncId に対応する非同期リソースが破棄されたときに呼び出されます。一部の非同期リソースの破棄はガベージ コレクション メカニズムに依存するため、メモリ リークが原因で、破棄イベントがトリガーされない場合があります。 5. promiseResolve(非同期ID) Promise コンストラクターの resolve 関数が実行されると、promiseResolve イベントがトリガーされます。場合によっては、一部の解決関数が暗黙的に実行されます。たとえば、.then 関数は新しい Promise を返し、この時点でこれも呼び出されます。 定数 async_hooks = require('async_hooks'); // 現在の実行コンテキストの asyncId を取得します eid は async_hooks.executionAsyncId() です。 // 現在の関数をトリガーする asyncId を取得します 定数 tid = async_hooks.triggerAsyncId(); // 新しい AsyncHook インスタンスを作成します。これらのコールバックはすべてオプションです。const asyncHook = async_hooks.createHook({ init、before、after、destroy、promiseResolve }); //AsyncHook.enable() を実行するには宣言する必要があります。 // 新しい非同期イベントのリッスンを無効にします。 asyncHook を無効にします。 関数 init(asyncId, type, triggerAsyncId, resource) { } 関数before(asyncId) { } 関数 after(asyncId) { } 関数destroy(asyncId) { } 関数promiseResolve(asyncId) { } 約束Promise は特別なケースです。十分に注意すれば、init メソッドの型には PROMISE がないことがわかります。 Promise の asyncId を取得するために ah.executionAsyncId() のみを使用する場合、正しい ID を取得できません。実際のフックを追加した後にのみ、async_hooks は Promise コールバックの asyncId を作成します。 つまり、V8 では asyncId を取得するための実行コストが高いため、デフォルトでは Promise に新しい asyncId を割り当てません。 定数 async_hooks = require('async_hooks'); 定数asyncHook = async_hooks.createHook({ init(asyncId, type, triggerAsyncId, resource) { }, 破棄(非同期ID) { } }) asyncHook を有効にします。 Promise.resolve(123).then(() => { console.log(`asyncId ${async_hooks.executionAsyncId()} トリガーId ${async_hooks.triggerAsyncId()}`); }); また、Promise は init および promiseResolve フックイベント関数のみをトリガーし、before イベントと after イベントのフック関数は Promise がチェーンされたときのみ、つまり .then/.catch 関数内で Promise が生成された場合にのみトリガーされます。 新しいPromise(resolve => { 解決する(123); })。次に、データ => { コンソールにログ出力します。 }) 上記には 2 つの Promise があり、最初の Promise は新しいインスタンス化によって作成され、2 番目の Promise はその後に作成されることがわかります (わからない場合は、以前の Promise ソース コードの記事を参照してください)。 ここでの順序は、新しい Promise を実行するときに、独自の init 関数が呼び出され、解決時に promiseResolve 関数が呼び出されます。次に、then メソッドで 2 番目の Promise の init 関数を実行し、次に 2 番目の Promise の before、promiseResovle、および after 関数を実行します。 例外処理登録された async-hook コールバック関数で例外が発生した場合、サービスはエラー ログを出力し、直ちに終了します。同時に、すべてのリスナーが削除され、プログラムを終了させるための 'exit' イベントがトリガーされます。 プロセスがすぐに終了する理由は、これらの async-hook 関数が不安定に実行されると、次に同じイベントがトリガーされたときに例外がスローされる可能性が高いためです。これらの関数は主に非同期イベントを監視するために使用されます。不安定な場合は、適時に検出して修正する必要があります。 非同期フックコールバックでログを出力するconsole.log 関数も非同期呼び出しであるため、async-hook 関数で console.log を再度呼び出すと、対応するフック イベントが再度トリガーされ、無限ループ呼び出しが発生します。したがって、async-hook 関数で追跡するには、同期ログを使用する必要があります。fs.writeSync 関数を使用できます。 定数 fs = require('fs'); 'util' が必要です。 関数debug(...args) { fs.writeFileSync('log.out', `${util.format(...args)}\n`, { フラグ: 'a' }); } [参考資料 - AsyncHooks] (https://nodejs.org/dist/latest-v15.x/docs/api/async_hooks.html) Node8 の AsyncHooks の非同期ライフサイクルに関するこの記事はこれで終わりです。Node AsyncHooks の非同期ライフサイクルに関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: Alibaba Cloud Centos7のインストールとSVNの設定
>>: Centos7.3 での mysql5.7 のインストールと設定のチュートリアル
目次Tomcat8のインストールと設定方法tomcat ダウンロードTomcat マネージャーを有効...
1. Mycatの適用シナリオMycat は幅広いシナリオに合わせて開発されており、新しいユーザーが...
Linux は iftop を使用してネットワーク カードのトラフィックをリアルタイムで監視します。...
概要: Oracle scottユーザーには4つのテーブルがあり、実験やデータ検証に便利です。現在は...
1. まずSELECT文を実行して、すべての切り捨て文を生成します。ステートメント形式: selec...
この記事は、この時期の「ピーターから奪ってポールに払う」という仕事のスタイルに対する私の不満から生ま...
プログラムサービスがgitlab ci/cdと統合されたk8sを使用してデプロイされている場合、gi...
この記事では、例を使用して、MySQL データベースのデータ テーブルの最適化、外部キーの使用、およ...
私たちが作成する Web ページでは、より多くの人々に訪問してもらいたい場合、検索エンジンを使用して...
目次開発環境ゲームエンジンのコンセプトCocos Creatorについてプロジェクト構造コード編集環...
UPDATE はロックしますか?以下のような場合、SQL文はロックされますか? テーブル1を更新しま...
システム トレイ アイコンは、今日でも魔法のような機能です。アイコンを右クリックして目的のアクション...
1. 仮想マシンをダウンロードする公式ダウンロードウェブサイト: https://www.vmwar...
vue+el-upload 複数ファイルの動的アップロード、参考までに具体的な内容は以下のとおりです...
目次1. 適用メソッドを置き換え、関数を呼び出すときにパラメータを処理する2. 残りパラメータ(残り...