Asynchronous Programming
Call stack
- コードが実行されるとき、必ずコールスタックが使われます.
- これは単に、実行中の関数とその後に実行される関数を記録しておくメモリ上の場所です.
- コールスタックは「先入れ先出し」方式を採用しています.
Callback Queue
- コールバックキューは、Call stackが空になった際に処理する必要のある関数のリストです.
- マウスイベントやタイマーイベントなど、JavaScriptエンジンの外部にタスクが提供されると、そのタスクに関数が提供されます.
- イベントが発火すると、関数はキューに入れられ、コードの実行を待ちます.
Event Loop
- イベントループは、コールスタックが空かどうかを常にチェックし、キューにアイテムがあるかどうかを確認しています.
- コールスタックが空の場合、イベントループはキューからアイテムを取得し、関数をスタックに追加してコードの実行ができるようにします.
coliss.com
Promise
then()
メソッドを使用する場合、catch()
、finally()
メソッドを使用して、Promiseがrejectされた場合のエラーを処理することができます.
ja.javascript.info
then
メソッドは、エラー処理に使用される第2引数を受け取ることが可能です.
then
の最初の引数は、promise が解決(resolve)されたときに実行され、結果を受け取ります.
then
の2つ目の引数は、promise が拒否(reject)されたときに実行され、エラーを受け取ります.
catch(function)
と動きは同じです.
- 下記のコード例は、第二引数を
then
に渡してエラーをキャッチしています.
getLatestComplaint()
.then(complaint => getUser(complaint.userId))
.then(user => {
console.log(user);
return notifyUser(user.uuid);
})
.then(status => console.log(status), err => console.log(err));
async
とawait
を使用する場合、try...catch
ステートメントを使用してエラーをキャッチすることができます.
ja.javascript.info
Promiseの state
値
- pending
- fulfilled
- rejected
Promise Chain
- 次の
then
メソッドには必ずreturn値を現在のthen
メソッドから渡さないといけない.
function promiseChain(param) {
.then(response => response.json())
.then(user => {
console.log(user);
});
}
- ちなみに、
.then(response => response.json())
は下記と同意になります.
.then(response => {
return response.json();
})
async
async
キーワードを使用して宣言された関数では、その関数内でawait
キーワードを使用することができます.
await
キーワードは、関数が非同期タスクの最終的な完了を待つことを許可します.
await
キーワードがない場合は、関数は通常通り実行されます.
async
関数は、戻り値を持つPromiseを返します.
console.log('message one');
async function testAsync() {
console.log('In async function: message two');
return 'success';
};
console.log('message three');
Promise.resolve('success').then((val) => console.log('Promise: message four'));
console.log('message five');
testAsync().then((val) => console.log('async function callback: message six'));
console.log('message seven');
await
がないasync
関数が呼ばれるので、callされた次に message two
がprintされていることを確認.
message one
message three
message five
In async function: message two
message seven
Promise: message four
async function callback: message six
await
- promiseが成立すると、解決された値がawaitされているpromiseから返されます.
- コードの実行は、promiseが解決されるまでブロックされます.
- エラー処理には
try...catch
文を使用する必要があります.
throw
キーワードは、async
関数の内部で使用することができます.
await
キーワードはasync
関数の内部でのみ使用することができます.
await
キーワードは、エラーを処理するために使用することはできません.
await
キーワードは、then
メソッドと結合する必要はありません.
async function getUserData(userId) {
try {
let data = await axios.get(`users/${userId}`);
console.log('sample data: ', data);
if (data.id) {
return data;
} else throw "Something went wrong";
} catch (error) {
console.log(error);
return null;
}
}
setTimeout()
setTimeout
メソッドは、指定された時間が経過した後に、特定のコードブロックを1回実行するために使用することができます.
setTimeout
メソッドは、コードの実行をブロックしない.
- 下記のように
setTimeout()
を呼び出すと、2つめのtimer
がdelayとなり、3つめのtimer
はwrapper関数に渡される値となる.
let timer = 3000;
let alertTimer = (time) => {
console.log(`Your ${time / 1000} seconds is over`);
}
setTimeout(alertTimer, timer, timer);
setTimeout
関数はメッセージ・キューに置かれ、スタックが空になった時点で実行される.
- イベントループで処理されるので、時間値を0に設定しても
setTimeout
コードが実行される前に、他のすべてのコードが実行を終了する必要があります. .
function showEventLoop(num) {
num++;
setTimeout(function() {
num = num * 10;
console.log(num);
}, 0);
num++;
};
showEventLoop(5);
setInterval()
setInterval
メソッドは、一定間隔でコードを実行します.
clearInterval()
メソッドで定期的な処理をキャンセルする.
- 関数に渡されたミリ秒数に基づいて処理されます.
setInterval
メソッドは、コードの実行をブロックしない.
- 各インターバルは、ハンドラ関数をメッセージキューに追加するイベントである.
- よって、下記のコードは、
first
、second
のconsole.log()
がまず実行され、その後でキューに追加されたsetInterval()
内のコードが処理される.
var cnt = 1;
console.log('first : ' + cnt);
var id = setInterval(function() {
cnt++
if (cnt > 5) {
clearInterval(id);
}
console.log('interval : ' + cnt);
}, 0);
console.log('second : ' + cnt);
while (cnt < 5) {
cnt++;
}
first : 1
second : 1
interval : 6
monitorEvents
monitorEvents
メソッドを使用すると、特定のイベントまたはイベントのカテゴリに対するイベントオブジェクトを表示できます.
- 最初のパラメータは、イベントを監視するオブジェクトです.
- 第2パラメータには、イベントのカテゴリー(「マウス」や「キー」など)、特定のイベント(「クリック」など)、または特定のイベントを複数含む配列を指定します.
monitorEvents(window, ['click', 'mouseup', 'mousedown', 'mousemove']);
monitorEvents(window, 'mouse');