この記事では、主に 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 に統合する方法WeChat でアプリを呼び出すために js を使用する方法?
以上がJavaScript を使用した非同期より良い解決策はありますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。