JavaScript非同期処理さんぷる

という名のおぼえがき

間違えているかもしれない


Promiseとawait

説明

Promise内の処理は非同期で行われます。

同期させたい場合はasync関数とawaitを使います。

Promise
let flag = true;
const promise1 = new Promise( ( resolve, reject ) => {
  if( flag ){
    resolve( 'resolve(成功)です' );
  }
  else{
    reject( 'reject(エラー)です' );
  }
})


promise1.then( result => {  // thenはresolveが返ってきた際に実行されます。
  console.log( result );    // > resolve(成功)です

}) .catch( error => {       // catchはrejectが返ってきた際に実行されます。
  console.error( error );   // > reject(reject(エラー))です

}) .finally( () => {        // finallyは結果の可否に関わらず実行されます。
  console.log( '処理が完了しました' );
});

// この例では成功が返ってきます。
await
async function inuGohan(){  // functionの前にasyncと書くことでawaitが使えるようになるよ

  promiseGohanShitaku();        // ごはんの支度をするよ
  inu.eat();                    // 支度中でも構わず食べようとするよ

  await promiseGohanShitaku();  // 支度が終わるまで待っててね
  inu.eat();                    // 待てと言えばちゃんと待てる子です
}

試してみよう

checkboxがfalseの時にreject(エラー)、trueの時にresolve(成功)を返します。

コード

      

複数の処理を同時に行う

説明

Promiseを配列に入れることで、複数の処理を同時に行うことができます。

配列に入れたPromiseは以下のメソッドに配列を渡すことで実行できます。

  1. Promise.all()
  2. Promise.allSettled()
  3. Promise.any()
  4. Promise.race()

いすれも配列の先頭から実行していきますが、結果を受け取った時の挙動が異なります。

それぞれの特徴
  1. Promise.all

    全てresolveであれば結果を配列にまとめて返します。
    rejectされた場合はその時点でエラーを返し、他の結果は返しません。

  2. Promise.allSettled

    すべての処理が終わった時に、各結果のオブジェクトを配列にまとめて返します。

    [
      { status: 'fulfilled', value: 'resolveの値' },  // 成功
      { status: 'rejected', reason: 'rejectの値' }  // エラー
    ]
  3. Promise.any

    最初に返ってきたresolveの値を返します。
    全てrejectだった場合は、エラーメッセージを返します。

  4. Promise.race

    最初に返ってきた結果を返します(可否は問わない)。

試してみよう

3つのPromiseを実行します。
2 → 1 → 3 の順で結果が返ってきます。

checkboxがfalseの時にreject(エラー)、trueの時にresolve(成功)を返します。

コード

      

プロミスチェーン

説明

Promiseの結果を受け取るthenメソッドは繋げていくことも可能です。

then()内でreturnされた値が次のthen()へ渡されます。

複数の非同期処理を順番に実行していきたい時に役に立ちますが、繋げすぎると可読性やパフォーマンスが低下するので、複雑な処理をしたい場合はasyncを使った方がいいかも。

thenが繋がるようす
new Promise( resolve => {
  resolve( 'ほげほげ' );
} )
  .then( result => {
    return `${ result }ふがふが`;  // returnされた値が次のthenへ
  } )
  .then( result => {  // result == 'ほげほげふがふが'
    return `${ result }ぴよぴよ`;
  } )
  .then( result => {  // result == 'ほげほげふがふがぴよぴよ'
    console.log( `${ result }おあー` );  // >ほげほげふがふがぴよぴよおあー
  } );

試してみよう

トリ○ク2で出てきた必ず5になる計算。
1回の計算毎に計算用の関数を実行、returnをし、次のthenへ渡しています。

計算用の関数も非同期関数ですが、0.5秒のタイマーを入れてみたので、結果を待ってから実行しているのがよくわかると思います。

1~100の範囲を超えた数値を指定した場合、エラーとなります。

コード

      

async

説明

awaitの件で出てきたasyncくんです。

asyncはpromiseの糖衣構文で、awaitやtryを用いることで

といったことが可能になります。

基本的な流れ
const async_kihon = async () => {
  try{
    new Promise( ( resolve, reject ) => {
      reject( 'awaitを付けないとcatchされないので気をつけて' );
    } );

    for( let i = 0; i < 2; i++ ){
      const result = await new Promise( ( resolve, reject ) => {
        if( !i ){  // 1回目
          resolve( 'resolveの場合、このまま先に進みます' );
        }
        else{  // 2回目
          reject( 'rejectの場合、catchに飛びます' );
        }
      } );

      console.log( result );  // この例では、2回目はrejectされているので実行されません
    }
  } catch( error ){
    console.error( error );
  };
}

試してみよう

配列の値を一つ一つ回し、セレクトボックスの値と比較します。

双方の値が合致したときにrejectします。

コード