プログラマが避けては通れないトピックの 1 つはコードの実行効率です。これはバックエンドとフロントエンドに当てはまります。したがって、async/await 非同期開発はコードの効率を向上させるためのすべての人にとって重要な知識ポイントです。これは Python と JS にも当てはまります。そこで、今日は JS に基づく async/await 非同期プログラミングについて話しましょう。
非同期
それでも、最初に基本概念である非同期について話しましょう。その対義語は同期です。根本原因を調査するには、コンピュータ原理におけるプロセスと実行キューについて話す必要があります。簡単に言うと、通常の状況で関数を実行します。現在の関数の実行中に、ファイル コンテンツの読み込みや応答の待機が発生すると、プログラムはブロック状態になり、すぐには応答しないか、新しいタスクの実行を継続しません。次に、例としてフロントエンドに基づいて電子メールを送信します。
(1) メール送信依頼
(2)メール送信
(3) ページはメールの送信を待ちます。
(4) ユーザーはページの応答を待ちます。
(5) ユーザーはイライラして、再試行するためにページを更新し始めます。
(6) 上記の手順を 2 ~ 3 回繰り返すと、ユーザーは悪口や悪口を残します。
(7) 悪いレビュー
上記の説明に基づくと、ブロッキングはコードの実行効率に影響を与えるだけでなく、ユーザー エクスペリエンスにとって非常に致命的であることがわかります。次に、非同期という概念があります。いわゆる非同期とは、実行が開始された後、プログラムは待機状態に入り、ブロック状態には入らないことを意味します。代わりに、待機後に結果が返されるまで次の関数を実行し続け、その後、再度応答します。明らかに、上記の問題を非常にうまく回避できます。フロントエンドに基づいて、私が最初に学んだ非同期は ajax、非同期リクエスト、ページの部分更新でした。その時はとても良いと感じていましたが、徐々に ajax は非同期リクエストのみであり、非同期が必要な関数には良い解決策がないことに気づきました。この場合、async と await があります。
非同期
関数の前に置かれたキーワードは、この関数が非同期関数であることを意味し、この関数の実行は次のコードの実行をブロックしませんが、非同期関数の呼び出しは通常の関数の呼び出しと同じですが、戻り結果は異なります。
<script>
async function say_hello() {
return "hello world"
}
console.log(say_hello()); //Promise 对象
console.log("hi man") //
</script>
Say_hello が非同期関数に変換された後、結果を直接返すのではなく、Promise オブジェクトを返すことがわかります。デバッグ モードを通して、Promise にいくつかのメソッドがあり、言葉の意味によるとライフ サイクルに似ていることがわかります。一つずつ呼び出してみましょう。
<script>
async function say_hello(f) {
if(f === 1){
return "hello world";
}else{
throw new Error("这里要发生错误"); //引发错误
}
}
say_hello().catch((args)=>{
console.log("catch 被调用了");
console.log(args);
console.log("catch 被调用了");
});
say_hello().finally(()=>{
console.log("finally 被调用了收尾");
});
say_hello().then((args)=>{
console.log("then 被调用了");
console.log(args);
console.log("then 被调用了");
});
console.log(say_hello(1));
</script>
コンストラクターについては後で詳しく説明するので、次の 3 つの関数がさまざまな状態で実行されることが明確にわかります。
方法 | 説明 |
---|---|
キャッチ | 非同期関数でエラーが発生したときに実行されるパラメータがあり、そのパラメータが間違った内容を受け取ります |
それから | パラメーターを使用すると、非同期関数が正常に完了した後に実行され、パラメーターは非同期関数によって返された結果になります。 |
ついに | エラー関数の実行完了後に実行、アクションがない場合はそれまでに実行 |
Promise オブジェクトには状態があります。Promise オブジェクトの状態が解決されると、then
メソッドで指定されたコールバック関数が呼び出されます。非同期関数がエラーをスローすると、状態は拒否され、catch
エラーを処理するためにメソッドで指定されたコールバック関数が呼び出されます。最後に、エラー後に終了する関数です。then メソッドで指定されたコールバック関数が動作中にエラーをスローした場合、それも catch メソッドによってキャプチャされることに注意してください。
待つ
await は待機中です。Promise オブジェクトの実行を待つために使用されます (ちょっとしたコルーチンです)。これは async 関数内でのみ使用でき、Promise オブジェクトではない場合、await 式の結果が待機対象となります。Promise オブジェクトを待っている場合、await はビジーになり、次のコードをブロックし、Promise オブジェクトが解決されるのを待ち、解決された値を await 式の演算結果として取得します。
<script>
async function say_hai(){
return "hi world"
}
async function say_hello() {
await say_hai().then((args)=>{
console.log("hi man")
}); //这里await右侧是一个异步函数,所以会阻塞程序,到这个异步函数执行完成之后,再往下执行
return "hello world"
}
say_hello().then((args)=>{
console.log("then 被调用了");
console.log(args);
console.log("then 被调用了");
});
console.log(say_hello());
</script>
<script>
function say_hai(){
return "hi world"
}
async function say_hello() {
const res = await say_hai(); //这里await右侧是一个常规函数,所以await只是拿到了函数返回的结果
console.log(res);
return "hello world"
}
say_hello().then((args)=>{
console.log("then 被调用了");
console.log(args);
console.log("then 被调用了");
});
console.log(say_hello());
</script>
したがって、await は、通常、非同期関数内の別の非同期関数の実行をブロックするために使用されます。プロダクション コンシューマと組み合わせると、非同期関数が生成し、非同期関数が消費します。await を使用してプロダクション内で消費を呼び出すと、1 つが生成され、1 つが呼び出され、プロダクションと呼び出し関数の実行の間で切り替わり、実行効果がより同期的になります。
ただし、注意してください:
await キーワードは、同期操作を実行するのと同じように、Promise が完了するまで後続のコードをブロックします。そのため、あまりにも多くの await を使用することは不適切であり、各 await が前の await が完了するまで待機することになり、非同期関数を使用する意味が失われます。