ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript の非同期エクスペリエンスのためのより優れたソリューションを共有する

JavaScript の非同期エクスペリエンスのためのより優れたソリューションを共有する

小云云
小云云オリジナル
2018-01-09 09:08:371559ブラウズ

この記事では主に 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 にパッケージ化されるため、意味がありません)


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 にまとめることができます。

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

4. async await に関する注意事項


1) 前述したように、await コマンドの背後にある Promise オブジェクトは非常に良好な実行結果をもたらします。拒否またはロジック エラーである可能性があるため、await をコードブロックをキャッチしてみてください。


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


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

上記のコードで、async1 と async2 が 2 つの独立した非同期操作である場合、firstAsync が完了するまで SecondAsync が実行されないため、このように記述するとさらに時間がかかります。 Promise.all:


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

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


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);
 });
}

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


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);
 });
}

しかし、3 つのメインが同時に出力されることがわかります。これは、ポストが順番ではなく同時に実行されることを意味し、3 つのメインが 1 秒間隔で出力されるという問題を解決できます。


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

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

関連する推奨事項:


JavaScript非同期とは

JavaScript非同期プログラミングの4つの方法の紹介

JavaScriptの非同期実行と操作フロー制御の例の詳細な説明

以上がJavaScript の非同期エクスペリエンスのためのより優れたソリューションを共有するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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