[JS]Promiseについて

21050 ワード

非同期およびコールバック


非同期


JAvascriptは非同期で処理できます.すなわち、先に実行されたコードが終了する前に、次のコードを実行することができる.
では、次のコードを見てみましょう.
const firstAsyncWork = () => {
  setTimeout(()=> {
    console.log("First Work!");
  }, 1000);
};

const secondWork = () => {
  console.log("Second Work!");
};


firstAsyncWork();
secondWork();
Javascriptを学んだ人は、上記のコードの結果を予測しやすいかもしれません.
Second Work!
First Work!
setTimeout非同期処理.1秒待ちではなくsetTimeoutを実行し、次のsecondWork関数を実行します.
なぜこのようにするのかは今日のテーマではありません.次の2つの文章を参照してください.
https://developer.mozilla.org/ko/docs/Web/JavaScript/EventLoop
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#what-is-the-event-loop

callback


順番に実行するには、callbackを使用して2つの関数を順番に実行します.
ダイヤルバックについてはhttps://ko.javascript.info/callbacksを参照してください.
const firstAsyncWork = (callback) => {
  setTimeout(()=> {
    console.log("First Work!");
    callback();
  }, 1000);
};

const secondWork = () => {
  console.log("Second Work!");
};

firstAsyncWork(secondWork);
このようにすれば順番に実行できる.
First Work!
Second Work!

成敗得失


非同期操作の成功と失敗に応じて異なる操作が必要な場合は、このようにコードを記述する必要があります.
const asyncWork = (sucessCallback, failureCallback) => {
  doSomeWorkCanFail((res, err)=>{
    if(res){
      sucessCallback(res)
    }
    else {
      failureCallback(err)
    }
  })
};

コールバックの問題


コールバックの欠点は,オーバーラップ時にコードを認識しにくいことである.
コードソース
loadScript('1.js', function(error, script) {

  if (error) {
    handleError(error);
  } else {
    // ...
    loadScript('2.js', function(error, script) {
      if (error) {
        handleError(error);
      } else {
        // ...
        loadScript('3.js', function(error, script) {
          if (error) {
            handleError(error);
          } else {
            // 모든 스크립트가 로딩된 후, 실행 흐름이 이어집니다. (*)
          }
        });

      }
    })
  }
});
この問題を解決するために、新しい方法が誕生しました.それは約束です.

Promise


紹介する


Promiseはclassとしてコンストラクション関数を使用します.以下のような形態を有する.
let promise = new Promise((resolve, reject) => {
  // 비동기 작업
});
ユーザは,注釈の一部に非同期操作を行うコードを記述するだけでよい.
Promiseを使用して最初の例を記述します.
const firstAsyncWork = () => {
  return new Promise((resolve, reject) => {
    setTimeout(()=> {
      console.log("First Work!");
      resolve();
    }, 1000);
  });
  
};

const secondWork = () => {
  console.log("Second Work!");
};

firstAsyncWork()
  .then(secondWork);
非同期操作を行った後、成功するか否かに応じてresolverejectをそれぞれ呼び出し、結果をパラメータとする.
Promiseを使用して2番目の例を記述します.
const asyncWork = () => {
  return new Promise((resolve, reject) => {
    doSomeWorkCanFail((res,err)=> {
      if(res){
        resolve(res);
      }
      else{
        reject(err);
      }
    });
  });
};

asyncWork()
  .then(sucessCallback)
  .catch(failureCallback)

Promiseの状態


Promiseの状態はいつも3つのうちの1つです.
  • Pending:初期状態にあり、解析または呼び出し拒否に応じて他の状態に切り替えることができます.
  • Fulfilled:他の状態に変換することはできません.変更しない値が必要です.(結果)
  • Rejected:他の状態に変換できず、変わらない理由が必要です.(エラーの原因)
  • 下図を見れば分かります.ソース(下図参照)

    finally

    finallyを使用すると、resolveでもrejectでも無条件に運転できます.
    const asyncWork = () => {
      return new Promise((resolve, reject) => {
        doSomeWorkCanFail((res,err)=> {
          if(res){
            resolve(res);
          }
          else{
            reject(err);
          }
        });
      });
    };
    
    asyncWork()
      .then(sucessCallback)
      .catch(failureCallback)
      .finally(cleanUpWork)
    ここでは、失敗の有無にかかわらず、cleanUpWork関数が実行されます.

    リファレンス


    https://promisesaplus.com/
    https://ko.javascript.info/callbacks
    https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Using_promises