解 説

Promiseとは

Promiseは非同期処理が完了した時に次の処理を約束したり、または失敗を表現するクラスです。

JavaScriptで非同期処理を行うには通常はコールバック関数を利用します。けれども、これはコールバック地獄を生み出す原因ともなります。
コールバックを使用せずにpromiseを使用することでスマートな記述をすることができるようになります。

Promiseのメソッド

  1. Promise(preocess) コンストラクター
  2. Promise.prototype.then(onfullfild,onrejected) インスタンスメソッド
  3. Promise.prototype.catch(onrejected) インスタンスメソッド
  4. Promise.all(iterable) スターティックメソッド
  5. Promise.race(iterable) スターティックメソッド

PromiseはES6で用意されたClassです。
非同期処理でPromiseを使うには、まずnew演算子でコンストラクタ関数を呼び出してオブジェクト(インスタンス化)を作ります。

  1. コンストラクターは「new Promise((resolve,reject)=>{})」でオブジェクトを作ることができます。
    Promiseコンストラクターは関数の引数を持っています。関数は無名関数で記述しますが、arow関数を使うことも可能です。
    そして{}の中は非同期処理する内容を記述します。
    さて、ここで無名関数で指定した引数の働きについて見ていきます。まず、第1引数の「resolve」には非同期処理終了後に正常終了した時に実行したい処理を定義します。つまりこれも関数にすることができます。
    次に、「reject」は処理に失敗した場合の処理を定義します。
  2. 「Promise.prototype.then(onfullfild,onrejected)」 非同期処理が終了して成功した場合に実行する内容を記述します。ドットでthen()をつないで次々に処理を実行することもできます。
  3. 「Promise.prototype.catch(onrejected)」は同期処理でなんらかの失敗が起こった時に処理をするものです。
  4. 「Promise.all(iterable)」については、複数のPromiseを設定しておいて全ての同期処理が終了してからiterableの処理を行うものです。
  5.                 

  6. 「Promise.race(iterable)」については、複数のPromiseを設定しておいて最初に同期処理が終了した段階でiterableの処理を行うものです。

Promiseと同期処理の実際

まずは簡単なサンプルです。
非同期処理をsetTimeout関数で行い、その処理が済んだら、次々に処理を実行する例です。
thenをメソッドチェーンでつないで記述している点に注目してください。もちろん、thenはいくつつないでもOKです。

単純なthen()の例

let myFirstPromise  = new Promise((resolve, reject) => {
    const result = 1
    setTimeout(() => resolve(result), 1000);
  });

 
myFirstPromise
  .then((result) => {
    console.log("done"+result);
    return result + 1;
  })
  .then((result) => {
    console.log("done"+result);
  })
  .catch((err) => {
    console.error(err);
  });

もう一度コールバック地獄の例で1秒ごとに表示させるものです。

コールバックの例

setTimeout(() => {
  console.log("done1");
  setTimeout(() => {
    console.log("done2");
    setTimeout(() => {
      console.log("done3");
      setTimeout(() => {
        console.log("done4");
      }, 1000);
    }, 1000);
  }, 1000);
}, 1000);

上のコールバック地獄をPromiseを使って記述した例です。then()のメソッドチェーンを上手に活用してコールバック地獄を解決したものです。

let myFirstPromise = num => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("done" + num);
      resolve(num);
    }, 1000);
  });
};

myFirstPromise(1)
  .then(result => {
    return myFirstPromise(result + 1);
  })
  .then(result => {
    return myFirstPromise(result + 1);
  });