' P '

whatever I will forget

Certified Javascript Developer Asynchronous Programming Section

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);
    })
     // the use of a second parameter for then function
    .then(status => console.log(status), err => console.log(err));
  • asyncawaitを使用する場合、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`);
    //implement alert
}

setTimeout(alertTimer, timer, timer);
  • setTimeout関数はメッセージ・キューに置かれ、スタックが空になった時点で実行される.
  • イベントループで処理されるので、時間値を0に設定してもsetTimeoutコードが実行される前に、他のすべてのコードが実行を終了する必要があります. .
function showEventLoop(num) {
  num++;  // 6
  // executed at the end
  setTimeout(function() {
    num = num * 10;
    console.log(num);  // 70
  }, 0);
  // executed before setTimeout
  num++; // 7
};

showEventLoop(5);

setInterval()

  • setIntervalメソッドは、一定間隔でコードを実行します.
  • clearInterval()メソッドで定期的な処理をキャンセルする.
  • 関数に渡されたミリ秒数に基づいて処理されます.
  • setIntervalメソッドは、コードの実行をブロックしない.
  • 各インターバルは、ハンドラ関数をメッセージキューに追加するイベントである.
  • よって、下記のコードは、 firstsecondconsole.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パラメータには、イベントのカテゴリー(「マウス」や「キー」など)、特定のイベント(「クリック」など)、または特定のイベントを複数含む配列を指定します.
// way1
monitorEvents(window, ['click', 'mouseup', 'mousedown', 'mousemove']);

// way2
monitorEvents(window, 'mouse');