JS 非同期スタック トレース: await が Promise よりも優れている理由

JS 非同期スタック トレース: await が Promise よりも優れている理由

概要

async/await と Promise の基本的な違いは、await fn() は現在の関数の実行を一時停止しますが、promise.then(fn) は fn 呼び出しをコールバック チェーンに追加した後、現在の関数の実行を継続することです。

const fn = () => console.log('hello')
定数a = 非同期() => {
  await fn() // fn の実行を一時停止する }
// a が呼び出されると、fn の実行が再開されます a() // "hello"

const promise = Promise.resolve()
// コールバックチェーンにfnを追加した後、fnの実行を継続します
promise.then(fn) // "こんにちは"

スタック トレースのコンテキストでは、この違いは非常に重要です。

Promise チェーン (desugared かどうかに関係なく) がいつでも未処理の例外をスローすると、JavaScript エンジンはエラー メッセージを表示し、(うまくいけば) 有用なスタック トレースをログに記録します。

開発者としては、通常の Promise を使用する場合でも、async await を使用する場合でも、これを期待するでしょう。

約束

非同期関数 b の呼び出しが解決されると、関数 c が呼び出されるシナリオを想像してください。

const b = () => Promise.resolve()
定数a = () => {
    b().then(() => c())
}

が呼び出されると、次のことが同期的に発生します。

  • b が呼び出され、将来のある時点で解決される Promise を返します。
  • .then コールバック (実際には c() を呼び出す) がコールバック チェーンに追加されます (V8 用語では、[...] が解決ハンドラーとして追加されます)。

その後、関数 a の本体のコード実行を終了します。 A は決して中断されず、B への非同期呼び出しが解決されるまでにコンテキストは消えてしまいます。

b (または c) が非同期に例外をスローした場合に何が起こるか想像してみてください。理想的には、B (または C) がそこから呼び出されたので、スタック トレースに A が含まれるはずですよね?を参照しなくなったので、これをどのように実行できるでしょうか?

これを機能させるには、JavaScript エンジンが上記の手順を超えて何かを実行する必要があります。つまり、機会があるたびにスタック トレースをキャプチャして保存する必要があります。

V8 では、スタック トレースは b によって返される Promise に添付されます。 Promise が満たされると、スタック トレースが渡され、c が必要に応じて使用できるようになります。

b()[a] -> b().then()[a] -> c[a?:a]

スタック トレースのキャプチャには時間がかかります (つまり、パフォーマンスが低下します)。これらのスタック トレースを保存するにはメモリが必要です。

非同期/待機

以下は、Promise の代わりに async/await を使用して記述した同じプログラムです。

const b = () => Promise.resolve()
定数a = 非同期() => {
  b() を待つ
  c()
}

await を使用すると、スタック トレースが await 呼び出しで収集されない場合でも、呼び出しチェーンを再開できます。

これは、A が中断され、B が解決されるのを待機しているために可能です。 b が例外をスローした場合、スタック トレースは要求に応じてこの方法で再構築できます。

c が例外をスローした場合、その時点ではまだ a のコンテキスト内にあるため、同期関数の場合と同じようにスタック トレースを構築できます。

次の推奨事項に従って、JavaScript エンジンがスタック トレースをより効率的に処理できるようにします。

  • Promise よりも async/await を優先します。
  • 不要な async/await 転送を回避するには、@babel/preset env を使用します。

以上がJS非同期スタックトレースの詳細と、なぜawaitがPromiseより優れているのかです。Javascriptの詳細については、123WORDPRESS.COMの他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • JS で async/await を使用して非同期呼び出しを実装する方法
  • NodeJsはasync/awaitを通じて非同期メソッドを処理します
  • async/await と promise (Node.js における非同期操作の問題)
  • JavaScript の非同期処理で待機時間を節約できますか?

<<:  WindowsとLinux間でファイルを転送する方法

>>:  Windows での MySQL のダウンロード、インストール、設定、使用に関するチュートリアル

推薦する

mysqlはエクスポートされたデータのsqlファイルから指定されたテーブルのみをインポートすることを実装します

シナリオ昨日、システムは dbAll.sql.gz という名前の特定のデータベースのすべてのテーブル...

表の最初の行と最初の列を固定し、適応型ウィンドウを実現するための CSS の例コード

今日のキャンパス採用筆記試験では、固定された最初の行と最初の列を実装し、幅をウィンドウの変更に適応さ...

HTML マルチメディア アプリケーション: Web ページにフラッシュ アニメーションと音楽を挿入する

1. HTML_falshアニメーションでのマルチメディアの応用(WebページへのFlashアニメー...

mysqlを完全にアンインストールします。個人テストです!

MySQL をクリーンアンインストールします。個人的にテストしたところ、今回はようやくうまくいきま...

HTML リンク アンカー タグと SEO におけるその役割の概要

<a> タグは主に、ハイパーリンクまたはアンカー リンクとも呼ばれるリンクとブックマーク...

JavaScript の組み込み Date オブジェクトの詳細な説明

目次日付オブジェクト日付オブジェクトの作成新しい日付()日付を取得する()取得日()月を取得する()...

入力が正しいにもかかわらず、MySQL 8.0 でアクセスが拒否される問題を解決する

最近、MySQL を学び始めました。インストールはスムーズに進み、インターネット上の既成のチュートリ...

CSSは親コンテナのdivをimg画像で埋め、コンテナのサイズに適応します。

ページに複数の画像を導入すると、画像のサイズがばらつくことがあります。しかし、それらを一貫したサイズ...

Linux システムで Code Cloud にプロジェクトをアップロードする方法

Code Cloudで新しいプロジェクトtest1を作成します。 公開鍵を取得するには次のコマンドを...

Linux カーネル デバイス ドライバーのメモリ管理に関する注意事項

/************************ * Linux メモリ管理 *********...

Nginx ドメイン名 SSL 証明書の構成 (Web サイトの http を https にアップグレード)

序文HTTP と HTTPS日常生活でよく使われる URL は、おおまかに次の 2 種類に分けられま...

ウェブ上の模倣と盗作に関する議論

2005年に業界に入ってから数か月後、労働者の日休みの期間中、1か月以上毎日12時まで残業をしました...

HiveメタデータをMySQLに設定するプロセス全体

Hiveのインストールディレクトリで、confディレクトリに入り、hive-site.xmlファイル...

vue-element-admin グローバル読み込み待機中

最近の要件:グローバルロード、すべてのインターフェースはロード待機機能を表示するかどうかを手動で制御...

HTML マークアップ言語 - フォーム

123WORDPRESS.COM HTML チュートリアル セクションに戻るには、ここをクリックして...