search
LoginSignup
123
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

Promise再入門① ~Promise基本編~

概要

PromiseはモダンJSでコーディングする際の肝の1つです。
Promiseを制するものが、モダンJSを制するものと言っても言い過ぎではないと思います。

ES7では、いよいよasync/awaitが実装されます。
今まで感覚で使っていた部分もあるPromiseを再度学習し直そうと思います。

Promiseとは

  • 非同期の処理を分かりやすく制御するオブジェクト
  • ES6に追加された機能の1つ
  • IE対応用のPolyfillも完備

Promiseの使い方

  • Promiseはnewして使う。
  • Promiseオブジェクトの第1引数は必ず関数
    • Promiseの第1引数の関数はは 成功時の処理失敗時の処理 を実行する引数(関数)を取得できる。
    • 成功 -> resolve(渡したい値)
    • 失敗 -> reject(渡したい値)
  • newされたPromiseは以下の関数を持つオブジェクトを返す
    • then(onFulfilled,onRejected),catch(onRejected)
    • thenでresolveされた時の処理、catchでrejectされた時の処理を受け取る
    • thenもcatchも引数を持つ関数を引数に取る
    • catchはエラーの処理が明確になるだけでなく、複数の非同期処理のエラーをまとめて制御する為にも使用される
    • 基本的には、catchを使って失敗時の処理を記述する

const promise = new Promise((resolve, reject) => {
  window.setTimeout(() => {
    resolve('OK');
  }, 2000);
});

promise
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.log(error);
  });

Promiseパターン

Promiseを使って同期的に処理

  • thenの中でPromiseを返せば、さらにthenを続けて記載する事が可能
  • 今回の例では、同期的に処理される。
    • func1の非同期処理の完了後、func2がコールバックされて、func2の非同期が完了後、次のthenに移っている。
    • Promiseを返さなければ、並列で処理されるthenとなる

const func1 = (num) => {
  return new Promise((resolve) => {
    window.setTimeout(() => {
      resolve(num);
    }, 3000);
  });
};

const func2 = (num) => {
  return new Promise((resolve) => {
    window.setTimeout(() => {
      resolve(num * num);
    }, 2000);
  });
};

func1(2)
  .then(func2)
  .then((result) => {
    console.log(result);
  })
  .catch((e) => {
    console.log(e);
  });
  • コールバック地獄が容易に想像出来るが下記の様な書き方も可能

...

func1(2)
  .then((res1) => {
    func2(res1)
      .then((res2) => {
        console.log(res2);
      });
  });

Promiseを使って並列処理して完了を検知する

  • 複数の非同期処理を並列で実行し、全てが完了したら情報を取得する
    • 非同期のメリット
  • Promise.all([Promise, Promise...])を使って、非同期な処理を並列で行い、全てがresolveになるタイミングでthenを取得する。
  • 並列処理しているもので1つでもrejectがあれば、catchされる。

const func1 = (num) => {
  return new Promise((res) => {
    window.setTimeout(() => {
      res(num + num);
    }, 500);
  });
};

const func2 = (num) => {
  return new Promise((res, rej) => {
    window.setTimeout(() => {
      rej(num * num);
    }, 2000);
  });
};

Promise.all([
  func1(2),
  func2(3)
])
.then((results) => {
  console.log(results);
})
.catch((e) => {
  console.log(e);
});

1つでも処理が返ってきたら実行する

  • Promise.race([Promise, Promise...])を使う事で、resolveもcatchでも何かしら処理が返ってきたら次の処理(thenやcatch)を実行する様に出来る。

const func1 = (num) => {
  return new Promise((res) => {
    window.setTimeout(() => {
      res(num + num);
    }, 500);
  });
};

const func2 = (num) => {
  return new Promise((res, rej) => {
    window.setTimeout(() => {
      rej(num * num);
    }, 2000);
  });
};


Promise.race([
  func1(3),
  func2(3)
])
.then((res) => {
  console.log(res);
})
.catch((e) => {
  console.log(e);
});

終わり

今回は基本編という事で、Promiseオブジェクトの最低限の知識をまとめました。
次回は、ES7で実装されるasync/awaitを使って、より柔軟にPromiseを使って見たいと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
123
Help us understand the problem. What are the problem?