Node.jsガイドから イベントループをブロックしないでください を読んでいました。言っている行がありました:
イベントループを決してブロックしないようにしてください。つまり、JavaScriptコールバックのそれぞれがすばやく完了する必要があります。もちろん、これは
await
やPromise.then
などにも当てはまります。
await
ingが解決するのに時間がかかっているデータベースへの一部のAPI呼び出しが解決に時間がかかっているとしたら、それはそのawait
呼び出しでイベントループをブロックしたことを意味しますか? ?
その後、私はいくつかの自己記述コードのテストを開始しましたが、テスト後もawait
によるブロックがどのように機能するかはまだわかりません。ここにいくつかのテストコードがあります:
仮定として、私はテストにエクスプレスを使用しています。この場合、/test
ルートに対して2つのAPI呼び出しを行うとイベントループがブロックされる理由を理解しています。
function someHeavyWork() {
// like calling pbkdf2 function
}
app.get('/test', (req, res) => {
someHeavyWork();
res.json(data);
});
しかし、この場合はそれは起こりません。
function fakeDBCall() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data);
}, 5000)
})
}
app.get('/test', async (req, res) => {
const data = await fakeDbCall();
res.json(data);
})
これは、async/await
の場合にブロックがどのように機能するかを理解していないためかもしれません。
見かけとは逆に、await
はブロックしません。それは約束よりも構文糖です。ブロックされるものはありません。コードが同期できるようにブロックしているように見えるかもしれませんが、それは約束を守るだけです。たとえば、これは同期的に見える場合があります。
const response = await fetch(…);
const json = await response.json();
const foo = JSON.parse(json); // Using json here, even though my request was async!
しかし、そうではありません。あなたがそれを砂糖を取り除いたら、あなたが得るすべてはノンブロッキングである約束です:
fetch(…)
.then(response => response.json())
.then(json => {
const foo = JSON.parse(json);
});
await
がブロックされていたら、それは絶対に破滅的でしょう。 JavaScriptランタイムは一般にシングルスレッドです。つまり、ユーザーの要求やその他のプロセスは、ファイルシステムを使用するなど、リクエストやその他の非同期操作を行うたびに停止します。関連するメモとして、これは動的インポートとともに トップレベルに対する主要な引数await
です。
awaitはnotイベントループをブロックします。実際、JavaScriptがawait
を検出すると、すぐに制御をイベントループに戻します。
Async関数はpromiseを返し、リクエストとレスポンスを渡しています。res.json(data)を変更してres.json(data)を返します。
非同期関数が値を返すとき、promiseは解決されます。関数にエラーが含まれている場合、res.json(data)を返す清潔さのために、promiseは拒否され、関数が解決されます。