こんにちは私は非同期と待機が舞台裏でどのように機能するかを理解するのに苦労しています。 「then」関数を使用して非ブロックコードを作成する約束があり、約束が解決された後に実行する必要があるすべての作業を配置できることを知っています。そして、並行して実行する作業は、then関数の外側に書き込むことを約束します。したがって、コードは非ブロッキングになります。ただし、async
await
が非ブロッキングコードを作成する方法がわかりません。
async function myAsyncFunction() {
try {
let data = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
// It will not run this line until it resolves await.
let result = 2 + 2;
return data;
}catch (ex){
return ex;
}
}
上記のコードを参照してください。 API呼び出しが解決されるまで先に進むことができません。それが私のコードをブロックするコードになる場合、それは約束よりもどのように優れていますか?それとも、async
とawait
について見逃したことはありますか?待機呼び出しに依存しないコードはどこに配置しますか?実行を待たずに作業を続けることができますか?
非同期待機の例で複製したいPromiseコードを追加しています。
function myPromiseAPI() {
myAPICall('https://jsonplaceholder.typicode.com/posts/1')
.then(function (data) {
// data
});
// runs parallel
let result = 2 + 2;
}
その名前が示すように、await
キーワードは、次の行を実行する前に、promiseが解決されるまで関数を「待機」させます。 await
の目的は、操作が完了するまでコードを待機させてから続行することです。
このコードとブロッキングコードの違いは、関数outsideは、関数が非同期操作の終了を待機している間も実行を継続できることです。
async
とawait
は、promiseの上にある単なる構文上の砂糖です。カバーされたプロミスを使用していても、通常の同期コードによく似たコードを記述できます。ここであなたの例を明示的にpromiseで機能するものに翻訳すると、次のようになります。
_function myAsyncFunction() {
return myAPICall('https://jsonplaceholder.typicode.com/posts/1')
.then(function (data) {
let result = 2 + 2;
return data;
})
.catch(function (ex) {
return ex;
});
}
_
ここでわかるように、_let result = 2 + 2;
_行は.then()
ハンドラー内にあります。つまり、myAPICall()
が解決されるまで実行されません。 await
を使用する場合も同様です。 await
は.then()
を抽象化するだけです。
心に留めておくべきことの1つ(そして、あなたが探している点だと思います)は、すぐにawait
を使用する必要がないことです。次のように関数を記述した場合、_let result = 2 + 2;
_行をすぐに実行できます。
_const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
// just starting the API call and storing the promise for now. not waiting yet
let dataP = myAPICall('https://jsonplaceholder.typicode.com/posts/1');
let result = 2 + 2;
// Executes right away
console.log('result', result);
// wait now
let data = await dataP;
// Executes after one second
console.log('data', data);
return data;
} catch (ex) {
return ex;
}
}
myAsyncFunction();
_
いくつかの明確化の後、あなたが本当に知りたかったのは、2つの非同期操作を1つずつ待つのを避け、代わりにそれらを並列に実行させる方法であることがわかります。実際、1つのawait
を次々に使用すると、最初のものが終了するまで、2番目は実行を開始しません。
_const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
let data1 = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
// logs after one second
console.log('data1', data1);
let data2 = await myAPICall('https://jsonplaceholder.typicode.com/posts/2');
// logs after one more second
console.log('data2', data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();
_
これを回避するために、あなたができることはstart両方の非同期操作を待たずに実行し、約束をいくつかの変数に割り当てることです。その後、両方の約束を待つことができます:
_const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
// both lines execute right away
let dataP1 = myAPICall('https://jsonplaceholder.typicode.com/posts/1');
let dataP2 = myAPICall('https://jsonplaceholder.typicode.com/posts/2');
let data1 = await dataP1;
let data2 = await dataP2;
// logs after one second
console.log('data1', data1);
console.log('data2', data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();
_
これを行う1つの代替方法は、いくつかの配列分解でPromise.all()
を使用することです。
_const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
// both myAPICall invocations execute right away
const [data1, data2] = await Promise.all([
myAPICall('https://jsonplaceholder.typicode.com/posts/1'),
myAPICall('https://jsonplaceholder.typicode.com/posts/2'),
]);
// logs after one second
console.log('data1', data1);
console.log('data2', data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();
_