ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript を使用した非同期より良い解決策はありますか?

JavaScript を使用した非同期より良い解決策はありますか?

亚连
亚连オリジナル
2018-06-13 11:40:301273ブラウズ

この記事では、主に JavaScript エクスペリエンスを非同期的に行うためのより良いソリューションについて説明します。この側面が必要な友人は、参考として参照してください。

1. 非同期ソリューションの進化の歴史
JavaScript の非同期操作は常に厄介な問題であるため、人々はそれに対するさまざまな解決策を提案し続けています。これは、最も初期のコールバック関数 (ajax の古い友人)、Promise (新しい友人ではない)、そして ES6 Generator (強力な友人) にまで遡ることができます。
数年前には有名な Async.js を使っていたかもしれませんが、コールバック関数は廃止されておらず、エラー処理も「コールバック関数の最初のパラメーターはエラーを渡すために使用される」という規則に従っていました。よく知られたコールバック地獄は、Generator がこの非同期スタイルを変更するまで、依然として顕著な問題でした。
しかし、ES7 の async await (Bunker の新しい友達) の登場により、非同期機構を持ちながら簡単に同期スタイルのコードを書くことができるようになり、現時点で最もシンプルでエレガントで最良のソリューションであると言えます。

2. async await 構文
async await 構文は比較的単純で、ジェネレーターの糖衣構文と考えることができます。アスタリスクや yield よりもセマンティックです。以下は、1 秒後に hello world を出力する簡単な例です。

function timeout(ms) {
 return new Promise((resolve) => {
  setTimeout(resolve, ms);
 });
}
async function asyncPrint(value, ms) {
 await timeout(ms);
 console.log(value)
}
asyncPrint('hello world', 1000);

await は非同期関数でのみ使用できます。通常の関数で使用すると、

await の後に Promise オブジェクトが報告されます。他の値も使用できますが、すぐに解決される Promise にパッケージ化されますが、これは意味がありません)

await は、実行を続行する前に Promise の結果が返されるのを待ちます

await は、 Promise オブジェクトですが、.then() を記述する必要はなく、戻り値を直接取得でき、上記のコードを微調整すると、戻り値の結果が hello world を出力することもできることがわかりました:

function timeout(ms) {
 return new Promise((resolve) => {
  setTimeout(_ => {resolve('hello world')}, ms);
 });
}
async function asyncPrint(ms) {
 let result = await timeout(ms);
 console.log(result)
}
asyncPrint(1000);

3. async awaitエラー処理

前述したように、await は Promise オブジェクトを待っていますが、.then() を書く必要はないので、実際には .catch() を書く必要はなく、try catch で直接エラーをキャッチできます。これにより、冗長で煩雑なエラー処理コードを回避できます。

function timeout(ms) {
 return new Promise((resolve, reject) => {
  setTimeout(_ => {reject('error')}, ms);//reject模拟出错,返回error
 });
}
async function asyncPrint(ms) {
 try {
   console.log('start');
   await timeout(ms);//这里返回了错误
   console.log('end');//所以这句代码不会被执行了
 } catch(err) {
   console.log(err); //这里捕捉到错误error
 }
}
asyncPrint(1000);

複数の await がある場合は、それらを try catch にまとめて配置できます。前述したように、await コマンドの背後にある Promise オブジェクトは拒否エラーまたは論理エラーを引き起こす可能性があるため、try catch コード ブロックに await を入れるのが最善です。

2) 複数の await コマンドの非同期操作の場合、依存関係がない場合は、それらを同時にトリガーします。

async function main() {
 try {
  const async1 = await firstAsync();
  const async2 = await secondAsync();
  const async3 = await thirdAsync();
 }
 catch (err) {
  console.error(err);
 }
}

上記のコードで、async1 と async2 が 2 つの独立した非同期操作である場合、 SecondAsync は firstAsync が完了した後でのみ実行されるため、このように記述するとさらに時間がかかります。 Promise.all を使用するとエレガントに処理できます。 :

const async1 = await firstAsync();
const async2 = await secondAsync();

3) await は非同期関数でのみ使用できます。通常の関数で使用すると、エラーが報告されます:

let [async1, async2] = await Promise.all([firstAsync(), secondAsync()]);

forEach 内部メソッドに async を追加するだけです:

async function main() {
 let docs = [{}, {}, {}];
 //报错 await is only valid in async function
 docs.forEach(function (doc) {
  await post(doc);
  console.log('main');
 });
}
function post(){
 return new Promise((resolve) => {
  setTimeout(resolve, 1000);
 });
}

ただし、メインとなるのは 3 つであることがわかります。これは、post が順次ではなく同時に実行されることを意味します。 for に変更すると、3 つのメインが 1 秒間隔で出力されます。

async function main() {
 let docs = [{}, {}, {}];
 docs.forEach(async function (doc) {
  await post(doc);
  console.log('main');
 });
}
function post(){
 return new Promise((resolve) => {
  setTimeout(resolve, 1000);
 });
}

つまり、 async await を使用した後はすっきりしました。非常に簡潔で洗練されたコードを使用してさまざまな派手な非同期操作を実装でき、ビジネス ロジックが複雑な場合でもコールバック地獄に陥る必要はありません。これが究極の解決策であるとはあえて言いませんが、確かに現時点で最もエレガントな解決策です。

上記は私があなたのためにまとめたものです。

関連記事:

zTree コードを Angular に統合する方法

ノードパッケージ化ツール Pkg (詳細なチュートリアル)

WeChat でアプリを呼び出すために js を使用する方法?

以上がJavaScript を使用した非同期より良い解決策はありますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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