この記事では、ES6 の async+await 同期/非同期ソリューションの詳細な説明を主に紹介します。この記事では、async + await のブロックを解除するための最も簡潔な方法を使用します。興味のある方は詳細をご覧ください。
非同期プログラミングは常に JavaScript の主要な問題です。プログラミング。非同期ソリューションに関しては、ES6 でまず状態管理に基づく Promise が登場し、次に Generator 関数 + co 関数、そして ES7 の async + await ソリューションが登場しました。
この記事は、最も簡潔な方法で非同期 + 待機のブロックを解除することを目的としています。
非同期プログラミングのいくつかのシナリオ
よくある質問から始めましょう: for ループで反復シーケンスを非同期に出力するにはどうすればよいですか?
この質問に答えるために、クロージャまたは ES6 で指定されている let ブロックレベルのスコープを使用することは簡単に考えられます。
for (let val of [1, 2, 3, 4]) { setTimeout(() => console.log(val),100); } // => 预期结果依次为:1, 2, 3, 4
ここで説明しているのは、均等に発生する非同期イベントであり、あらかじめ決められた順番で非同期キューにキューイングされて実行を待っています。
非同期が均等に発生しない場合、非同期キューに登録される順番が狂います。
for (let val of [1, 2, 3, 4]) { setTimeout(() => console.log(val), 100 * Math.random()); } // => 实际结果是随机的,依次为:4, 2, 3, 1
返される結果は順序が狂っていて制御不能ですが、これが最も現実的な非同期です。しかし、別の状況として、ループ内で前の非同期実行を完了させ、次の非同期実行を再度実行したい場合はどうすればよいでしょうか?
for (let val of ['a', 'b', 'c', 'd']) { // a 执行完后,进入下一个循环 // 执行 b,依此类推 }
これは単なる複数の非同期「シリアル」ではありませんか!
非同期操作をコールバックに入れ子にしてコールバックする方法で、この問題は解決されます。あるいは、Promise + then() を使用してレイヤーをネストすることでも、問題を解決できる可能性があります。ただし、このネストメソッドをループで記述することに固執すると、非常に手間がかかると思います。もっと良い方法はないでしょうか?
非同期同期ソリューション
想像してみてください。データのバッチをサーバーに送信したい場合、前のバッチが正常に送信された場合 (つまり、サーバーが成功の応答を返した場合) にのみ、次のデータ バッチを送信できるようになります。送信されない場合、送信は終了します。これは、「for ループ内の相互依存した非同期操作」の典型的な例です。
明らかに、この「シリアル」非同期は実際には同期とみなすことができます。アウトオブオーダーの非同期よりも時間がかかります。論理的に言えば、ブロックを「スキップ」して時間を短縮するために、プログラムを非同期で実行する必要があります。しかし逆に、一連の非同期「シリアル」が必要な場合、どのように適切にプログラムすればよいでしょうか?
この「シリアル」非同期については、ES6 はこの問題を非常に簡単に解決します。
async function task () { for (let val of [1, 2, 3, 4]) { // await 是要等待响应的 let result = await send(val); if (!result) { break; } } } task();
文字通り、このサイクルです。結果が得られたら、次のサイクルが実行されます。したがって、ループが終了するまで、実行するたびにループが一時停止 (「スタック」) されます。このコーディング実装により、ネストされた「コールバック地獄」の問題が効果的に排除され、認知的困難が軽減されます。
これは、非同期の問題を同期するための解決策です。この解決策に関して、Promise が主に非同期コールバックの問題を解決するのであれば、async + await は主に非同期の問題の同期化と非同期プログラミングの認知的負担の軽減の問題を解決します。
async + await 「外側は違うけど、内側は同じ」
以前この API に触れたとき、面倒なドキュメントを見て、async + await は主に非同期の問題を解決するために使用されるものだと思いましたそして同期。
実際にはそうではありません。上記の例からわかるように、async キーワードは非同期関数を宣言します。この非同期関数の本体には、動作が同期的に実行されることを通知する await ステートメントの行があり、上下の隣接するコードが実行されます。一行ずつ順番に。
この形式的なものをもう一度翻訳すると、次のようになります。
1. async 関数が実行された後、常に Promise オブジェクトが返されます
2. await が配置されているステートメントの行は同期です
このうち、1 は From を説明します。外部では、タスクメソッドは実行後に Promise オブジェクトを返すので、タスクが非同期メソッドであることがわかります。次のように使用されることに疑いの余地はありません。
task().then((val) => {alert(val)}) .then((val) => {alert(val)})
2 は、タスク関数内で非同期が同期に「カット」されたことを示しています。全体としては、実行に少し時間がかかる関数にすぎません。
1と2を組み合わせると、形式的には「タスク全体は非同期関数であり、内部部分はすべて同期している」ことを「外見は違うが中身は同じ」といいます。 。
全体は非同期関数であり、理解するのは難しくありません。実装に関して言えば、言語レベルでは、async キーワードが呼び出されるとき、関数の実行の最後に Promise が強制的に追加されます。その応答は次のとおりです。内部は同期しています。実際、await 呼び出しにより、次のステートメント (関数) が再帰的に実行されます。結果が取得され、そのステータスが変更されるまでは解決されません。解決が完了した後でのみ、コードの await 行が完了したとみなされます。次の行まで実行されます。したがって、外側に大きな for ループがありますが、for ループ全体が順番にシリアル化されます。
したがって、上記のフレームワークの外観だけから、async + await の意味を理解するのは難しくありません。使い方はとても簡単ですが、Promise はマスターする必要がある基本的な部分です。
秉承本次《重读 ES6》系列的原则,不过多追求理解细节和具体实现过程。我们继续巩固一下这个 “形式化” 的理解。
async + await 的进一步理解
有这样的一个异步操作 longTimeTask,已经用 Promise 进行了包装。借助该函数进行一系列验证。
const longTimeTask = function (time) { return new Promise((resolve, reject) => { setTimeout(()=>{ console.log(`等了 ${time||'xx'} 年,终于回信了`); resolve({'msg': 'task done'}); }, time||1000) }) }
async 函数的执行情况
如果,想查看 async exec1 函数的返回结果,以及 await 命令的执行结果:
const exec1 = async function () { let result = await longTimeTask(); console.log('result after long time ===>', result); } // 查看函数内部执行顺序 exec1(); // => 等了 xx 年,终于回信了 // => result after long time ===> Object {msg: "task done"} //查看函数总体返回值 console.log(exec1()); // => Promise {[[PromiseStatus]]: "pending",...} // => 同上
以上 2 步执行,清晰的证明了 exec1 函数体内是同步、逐行逐行执行的,即先执行完异步操作,然后进行 console.log() 打印。而 exec1() 的执行结果就直接是一个 Promise,因为它最先会蹦出来一串 Promise ...,然后才是 exec1 函数的内部执行日志。
因此,所有验证,完全符合 整体是一个异步函数,内部整个是同步的 的总结。
await 如何执行其后语句?
回到 await ,看看它是如何执行其后边的语句的。假设:让 longTimeTask() 后边直接带 then() 回调,分两种情况:
1)then() 中不再返回任何东西
2) then() 中继续手动返回另一个 promise
const exec2 = async function () { let result = await longTimeTask().then((res) => { console.log('then ===>', res.msg); res.msg = `${res.msg} then refrash message`; // 注释掉这条 return 或 手动返回一个 promise return Promise.resolve(res); }); console.log('result after await ===>', result.msg); } exec2(); // => 情况一 TypeError: Cannot read property 'msg' of undefined // => 情况二 正常
首先,longTimeTask() 加上再多得 then() 回调,也不过是放在了它的回调列队 queue 里了。也就是说,await 命令之后始终是一条 表达式语句,只不过上述代码书写方式比较让人迷惑。(比较好的实践建议是,将 longTimeTask 方法身后的 then() 移入 longTimeTask 函数体封装起来)
其次,手动返回另一个 promise 和什么也不返回,关系到 longTimeTask() 方法最终 resolve 出去的内容不一样。换句话说,await 命令会提取其后边的promise 的 resolve 结果,进而直接导致 result 的不同。
值得强调的是,await 命令只认 resolve 结果,对 reject 结果报错。不妨用以下的 return 语句替换上述 return 进行验证。
return Promise.reject(res);
最后
其实,关于异步编程还有很多可以梳理的,比如跨模块的异步编程、异步的单元测试、异步的错误处理以及什么是好的实践。All in all, 限于篇幅,不在此汇总了。最后,async + await 确实是一个很优雅的方案。
以上がES6のasync+await同期・非同期ソリューションの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

ドリームウィーバー CS6
ビジュアル Web 開発ツール

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

WebStorm Mac版
便利なJavaScript開発ツール
