【JavaScript】promiseオブジェクトとは?メリットや使い方

この記事からわかること

  • promiseとは?
  • 3つのpromisestatusの違い
  • 使い方メリット

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

JavaScriptを学び出した私ですが「promise」についてなかなかうまく理解できなかったので備忘録も兼ねてまとめていきます。不備や至らぬ点、勘違いなどがありましたら教えていただけると助かります。

promise(プロミス)のメリット

promise(プロミス)とはJavaScriptの中の非同期処理の結果を取得できる仕組みのことです。

非同期処理とは「処理の終了を待たずに次の処理を行うこと」。JavaScriptは基本的に非同期で処理が進んでいくので例えば以下のようなコードの場合希望の順番に出力されません。

console.log("1回目");

setTimeout(() => {
  console.log("2回目");
},1000);

console.log("3回目");

// 結果
1回目
3回目
2回目

しかしこのようにJavaScriptが非同期で処理を行ってくれることで時間のかかる処理やタイミングのずれた処理を後続の処理に影響を与えることなくこなすことができているのは大きなメリットでもあります。

非同期処理が終了した後に処理を行うために役に立つのがpromiseです。promiseを使って先程のコードを書くと以下のようになり、希望の順番通りに出力されるようになります。

console.log("1回目");

const promise = new Promise((resolve, reject) => {

  setTimeout(() => {
        console.log("2回目");
        // これは成功させた時の処理なので resolve関数を呼び出す
        resolve();
  },1000);
})

promise.then((value) => {
  // 2回目の出力が成功したら3回目を表示
  console.log("3回目");
});
// 結果
1回目
2回目
3回目

promiseの最大のメリットは非同期処理終了後の結果に応じて処理を分岐できることです。これによりプログラムの中で行いたい処理の順番を明確に指定することができます。promise(約束)の意味通り、意図した処理順番を約束してくれるのがpromiseのメリットだと思います。

インスタンス化したpromiseの中では、非同期処理が成功なら「resolve(日本語で解決の意)」失敗なら「reject(日本語で拒絶の意)」という関数を呼び出します。プロミスを使うことで非同期処理通信の成否によって処理を分岐させることが可能になります。

まとめ

promiseの正体と3つのステータス

promiseの正体はオブジェクトです。使用するにはnew演算子を使ってインスタンス化します。インスタンス化したpromiseオブジェクトを表示させると以下のように表示されます。

const promise = new Promise((resolve, reject) => {
});
console.log(promise);
// Promise {} ~~ Object[[PromiseState]]: "pending"[[PromiseResult]]: undefined

promiseオブジェクトはpromiseStatusというプロパティを保持していて3つの状態に変化しながら管理されています。

consoleでオブジェクトを出力すれば現在のステータスを確認できます。ステータスが成功であればthenメソッドで、失敗であればcatchメソッドで後続の処理を記述することができます。

ステータスの値を切り替える方法は引数に渡されているresolverejectという2つのコールバック関数(コールバック関数とは?)です。promiseの中でどちらかのコールバック関数を実行することでステータスの値が切り替わります。

例えばステータスを成功に変えたい場合は、resolve関数を実行します。 resolve関数の前に任意の処理を記述すれば通常のコードのように上から順番に処理されていくので、「その処理が終わればステータスが切り替わる」ような仕組みを作ることができます。

const promise = new Promise((resolve, reject) => {
  // ここに結果を取得したい処理を記述
  resolve('成功!');
});

promise.then((value) => {
  console.log(value);
  // 成功!
});

promiseは自動で中に記述した処理結果を取得するわけでなく、自分でこの処理が終わったら成功(resolve関数を呼び出す)、この処理なら失敗(reject関数を呼び出す)といったようにルートを作っていきながら使います。

コールバック関数(resolveとreject)を使ってステータスを変更した後はthenメソッドcatchメソッドを使って後続の処理を記述していきます。

まとめ

コールバック関数とthenメソッド

ここでは先程出てきた2つのポイントをもう少し深掘りしたいと思います。興味がなければ飛ばしてください。

promiseを扱う上で重要になってくるのは先ほど登場した3つ。

コールバック関数とは?

コールバック関数とは関数の中で実行される関数のことを指します。通常関数を定義したら以下のように実行します。

function hello() {
  return 'hello";
}
hello(); // 結果:hello

JavaScriptでは関数も変数の中に格納して扱うことができます。なのでこの関数を例えば変数funcに格納して呼び出しの際に引数として渡すこともできるのです。

funcHello = function hello() {
return 'hello";
}

function callMethod(func) {
  func();
}

callMethod(funcHello);; // 結果:hello

ここでいうcallMethodの中で呼び出している関数(ここでいうfuncHello)をコールバック関数と呼びます。自分で実行するのではなく、他の関数から呼び出されることを前提として定義実行されます。

thenメソッドとは

thenメソッドはpromise statusresolvedの時に後続に処理させたいコードを記述できるメソッドです。promiseオブジェクトに対してthenメソッドを呼び出す形で使用します。thenメソッドの引数にはresolve関数の引数に指定した値を受け取ることもできます。

promise.then(onFulfilled[, onRejected]);

promise.then(value => {
  // resolve(成功)の時に実行させたい処理
}, reason => {
  // reject(失敗)の時に実行させたい処理
});

thenメソッドは戻り値としてpromiseオブジェクトを返すのでさらにここからメソッドチェーンで繋げることができます。メソッドチェーンでの直列処理については後述します。

catchメソッドとは

rejectedの時に後続の処理を記述する場合はcatchメソッドを使います。使い方はthenメソッドと変わりません。こちらも同様にプロミスオブジェクトを返すのでメソッドチェーンが使用できます。

promise.catch(() => {
console.log("rejectしたよ");
});

メソッドチェーンを使った直列処理

promiseを使うことで非同期処理が絡んでも処理の順番を約束してくれることがわかりました。では実際に希望の順番に処理させる実際の方法を見ていきます。

ここで実現したいことは3つの処理を順番通りに行うことです。非同期の処理が絡むことによって順番がややこしくなりがちなコードをpromiseを使って記述していきます。

const promise = new Promise((resolve, reject) => {
    console.log("即座に表示");
    setTimeout(() => {
      console.log("1秒後に表示");
      resolve('1秒後が成功したお');
    }, 1000);

})
.then((val) => {
  console.log(`then1: ${val}`);
  return val;
})
.catch((val) => {
  console.log(`catch: ${val}`);
  return val;
})
.then((val) => {
  console.log(`then2: ${val}`);
});

// 結果:
即座に表示
1秒後に表示
1秒後が成功したお
then1:1秒後が成功したお
then2:1秒後が成功したお

このようにpromiseを使うことで非同期の処理が絡んだ(1秒後に処理するなど)場合でも意図した通りの順番で処理を行わせることができます。またresolveの引数にデータを与えることもできます。メソッドチェーンで受け取るにはthenメソッドの引数に適当な変数を用意して受け取ってください。

おすすめ記事:

ついでにアロー関数の記述方法MEMO

アロー関数を使うことで関数が簡単に書けるようになります。

●通常
function (a){
  return a + 100;
}

●アロー関数
(a) => {
  return a + 100;
}

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index