ホームページ ウェブフロントエンド jsチュートリアル ES6 非同期 + 待機同期/非同期ソリューション

ES6 非同期 + 待機同期/非同期ソリューション

Feb 05, 2018 pm 02:17 PM
同期する プラン

この記事では、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 确实是一个很优雅的方案。

相关推荐:

让Express支持async方法分享

NodeJs通过async和await处理异步的方法

Node.js中如何使用async函数

以上がES6 非同期 + 待機同期/非同期ソリューションの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

win11でヘッドフォンとスピーカーを同時に再生する問題を解決する win11でヘッドフォンとスピーカーを同時に再生する問題を解決する Jan 06, 2024 am 08:50 AM

一般的に、同時に使用する必要があるのはヘッドフォンまたはスピーカーのいずれか 1 つだけですが、Win11 システムでヘッドフォンとスピーカーが同時に鳴るという問題が発生したと友人が報告しています。 Realtek パネルでオフにすれば問題ありません。以下を見てみましょう。 win11 でヘッドフォンとスピーカーが一緒に聞こえる場合はどうすればよいですか? 1. まず、デスクトップで「コントロール パネル」を見つけて開きます。 2. コントロール パネルに入り、「ハードウェアとサウンド」を見つけて開きます。 3. 次に、「」を見つけます。 Realtek High Definition" とスピーカーのアイコン。オーディオマネージャー" 4. [スピーカー] を選択し、[リアパネル] をクリックしてスピーカー設定に入ります。 5. 開くとデバイスの種類が表示されるので、ヘッドフォンをオフにしたい場合は、「ヘッドフォン」のチェックを外します。

同期したフォルダー内の 1 つ以上のアイテムが Outlook エラーと一致しません 同期したフォルダー内の 1 つ以上のアイテムが Outlook エラーと一致しません Mar 18, 2024 am 09:46 AM

同期フォルダー内の 1 つ以上のアイテムが Outlook のエラー メッセージと一致しない場合は、会議アイテムを更新またはキャンセルしたことが原因である可能性があります。この場合、ローカル バージョンのデータがリモート コピーと競合していることを示すエラー メッセージが表示されます。この状況は通常、Outlook デスクトップ アプリケーションで発生します。同期したフォルダー内の 1 つ以上のアイテムが一致しません。競合を解決するには、プロジェクトを開いて操作を再試行します。同期フォルダー内の 1 つ以上のアイテムが Outlook エラーと一致しない問題を修正する Outlook デスクトップ バージョンでは、ローカルの予定表アイテムがサーバー コピーと競合すると問題が発生する可能性があります。ただし幸いなことに、それを助ける簡単な方法がいくつかあります

検証可能な AI に向けて: 形式手法の 5 つの課題 検証可能な AI に向けて: 形式手法の 5 つの課題 Apr 09, 2023 pm 02:01 PM

人工知能は、人間の知能を模倣しようとするコンピューティング システムであり、学習、問題解決、合理的な思考と行動など、知能に直観的に関連する人間の機能が含まれます。広義に解釈すると、AI という用語は、機械学習などの密接に関連する多くの分野をカバーします。 AI を多用するシステムは、医療、交通、金融、ソーシャル ネットワーク、電子商取引、教育などの分野で社会に大きな影響を与えています。この社会的影響の増大は、人工知能ソフトウェアのエラー、サイバー攻撃、人工知能システムのセキュリティなど、一連のリスクと懸念ももたらしています。したがって、AI システムの検証の問題、および信頼できる AI というより広範なテーマが研究コミュニティの注目を集め始めています。 「検証可能なAI」を確認

MySQL データの移行と同期: 複数のサーバー間で MySQL データの移行と同期を実現する方法 MySQL データの移行と同期: 複数のサーバー間で MySQL データの移行と同期を実現する方法 Jun 15, 2023 pm 07:48 PM

MySQL は、さまざまな Web アプリケーション、エンタープライズ システムなどで広く使用されている、非常に人気のあるオープン ソースのリレーショナル データベース管理システムです。最新のビジネス アプリケーション シナリオでは、より高い可用性とパフォーマンスを提供するために、ほとんどの MySQL データベースを複数のサーバーにデプロイする必要があり、それには MySQL データの移行と同期が必要です。この記事では、MySQL のデータ移行と複数サーバー間の同期を実装する方法を紹介します。 1. MySQL データ移行 MySQL データ移行とは、MySQL サーバーでのデータ移行を指します。

win10 クリップボードと携帯電話を同期する方法を説明します win10 クリップボードと携帯電話を同期する方法を説明します Jan 06, 2024 am 09:18 AM

win10 クリップボードの非常に便利な機能は、クロスデバイス クラウド ストレージ機能です。これは非常に便利で、ユーザーが PC デバイスとモバイル デバイスで同時にコピー アンド ペーストするのに役立ちます。設定方法は非常に簡単で、システム内のクリップボードに設定するだけです。 win10 クリップボードを携帯電話に同期する 1. まず、左下隅の [スタート] をクリックして設定を入力します。 2. 次に「システム」をクリックします。 3. 左側の「クリップボード」を選択します。 4. 最後に、右側の「デバイス間同期」で「ログイン」をクリックし、携帯電話を選択します。

Windows 11 の OneDrive で同期する特定のフォルダーを選択する方法 Windows 11 の OneDrive で同期する特定のフォルダーを選択する方法 Apr 13, 2023 pm 04:22 PM

システム上の OneDrive アプリは、すべてのファイルとフォルダーをクラウドに保存します。ただし、ユーザーは特定のファイルやフォルダーを保存したくない場合があり、サブスクリプションなしで 5 GB に制限されている OneDrive の領域を占有することもあります。これを行うには、ユーザーがクラウド上で同期するファイルまたはフォルダーを選択できるようにする設定が OneDrive アプリにあります。これをお探しの場合は、この記事が Windows 11 の OneDrive で同期するフォルダーまたはファイルを選択するのに役立ちます。 Windows 11 の OneDrive で同期する特定のフォルダーを選択する方法 注: OneDrive アプリが接続され、同期されていることを確認してください

PHP の高同時処理におけるスレッド プール最適化ソリューション PHP の高同時処理におけるスレッド プール最適化ソリューション Aug 11, 2023 am 10:45 AM

PHP のスレッド プール最適化ソリューション 高同時実行処理 インターネットの急速な発展とユーザー ニーズの継続的な増大に伴い、最新の Web アプリケーション開発では高同時実行性が重要な問題となっています。 PHP では、シングルスレッドの性質のため、大量の同時リクエストを処理するのは困難です。この問題を解決するには、スレッド プールの概念を導入することが効果的な最適化ソリューションです。スレッド プールは、多数の同時タスクを実行するために使用される再利用可能なスレッドのコレクションです。その基本的な考え方は、スレッドの作成、破棄、管理を分離し、スレッドを再利用することでスレッドの数を減らすことです。

Baidu クラウド同期ディスクを同期する方法 Baidu クラウド同期ディスクを同期する方法 Feb 23, 2024 pm 01:22 PM

Baidu Cloud Sync Disk を同期するにはどうすればよいですか? Baidu Cloud Sync Disk で同期するファイルを選択できますが、ほとんどのユーザーは Baidu Cloud ファイルを同期する方法を知りません。次に、エディターが提供する Baidu Cloud Sync Disk 同期方法のグラフィック チュートリアルです。興味のあるユーザーはぜひ見に来てください! Baidu クラウド同期ディスクを同期する方法 1. まずコンピュータのデスクトップに入り、[Baidu クラウド同期ディスク] アイコンを右クリックし、[設定] を選択します; 2. 次にサービス ウィンドウを展開し、[詳細設定] ページに切り替えて、 [フォルダの選択]; 3. 最後に以下のようなページに切り替わり、同期が必要なファイルにチェックを入れて[OK]をクリックします。

See all articles