JavaScriptのPromise/async/awaitサンプル!実際に操作し理解しよう!両コードを比較し違いを学ぼう!ダウンロード可能

JavaScriptのPromise/async/awaitサンプル!実際に操作し理解しよう!両コードを比較し違いを学ぼう!ダウンロード可能
JavaScriptのPromise/async/awaitサンプル!実際に操作し理解しよう!両コードを比較し違いを学ぼう!ダウンロード可能

 

 
読了目安:415

Are you want to translate this page to English? Please click this link to translate via ‘©Google Translate'!

ganohr.net favicon


みなさんこんにちは! ガノー(Ganohr)です! (≧▽≦)

JavaScript’でプログラミングを行っていると、どうしても避けて通れないのが非同期処理です。

非同期通信などが必要になる局面も多く、今後一層さけて通れなくなります。

しかし、JavaScriptで実際に非同期処理を実現するための「Promise」や「async/await」の解説は、実際に動かして理解できるようなサンプルがほとんど存在しないことに気が付きました。

ほとんどどが呼び出し方のサンプルだけに留まっており、あまり初心者向けにはなっていないのです。初心者向けとしては、実際に動かして確認できる方がサンプルとして適切です。

そこで本記事では、「実際に動かして動作を確認できるコード」を公開し、解説します。

 

【本記事で学べる内容】

  • JavaScriptのPromiseの基本がわかる
  • JavaScriptのasync/awaitの基本がわかる
  • JavaScriptのPromsieとasync/awaitの対応、その違いがわかる
  • JavaScriptのPromiseとasync/awaitを用いて、実際に操作して学べるサンプルと解説がある
 
更新履歴
2021/01/27 公開
 

JavaScriptのPromiseとは?

JavaScriptのPromiseとは?(装飾用画像)
JavaScriptのPromiseとは?非同期処理のための約束事!

JavaScriptの‘Promise’(プロミス、約束の意味)とは、非同期処理を実現するための機能です。

以下、私が寄稿した記事から引用しておきます。

JavaScriptのPromiseとは?入門用に分かりやすく解説! Capa.inc - Promiseとは?
Promise(プロミス)とは、JavaScriptで非同期処理を実現するための機能です。端的に言えば、Promiseは日本語で「約束事」と訳されるように、「非同期処理を記述する際の決まり事」です。

この決まり事を実現するために、Promiseオブジェクトを生成し、そのオブジェクトを介して非同期処理や同期処理を実現します。

また現在Internet Explorerを除くPC/スマートフォンのほとんど全てのモダンブラウザで基本的な機能が動作する点もPromiseの特徴といえます。

 

非同期処理を「Promiseオブジェクト」を用いて、決まり事を守りながら実現します。Promiseオブジェクトとは、new Promise(() => {~})といった風に生成したものです。

この際のPromiseオブジェクトの決まりごとは、以下の3つに集約されます。

【Promiseの3つの決まりごと】

  • JavaScriptのPromiseはメソッドチェーンで記述する
  • JavaScriptのPromiseは成功時にresolveメソッドを実行し、失敗時にrejectメソッドを実行する
  • JavaScriptのPromiseは定義時即座に実行される

JavaScriptのPromiseはメソッドチェーンで記述する


錆びた古いチェーンの懐中時計
JavaScriptのPromiseはメソッドチェーンを用いて記述する

JavaScriptのPromiseを用いた非同期処理の記述は、メソッドチェーンを用いて行います。

メソッドチェーンとは、処理を連続して同じインスタンスで継続していく際に、インスタンスの指定を省略できる記法です。

もしもメソッドチェーンというものに聞き覚えがない場合、別言語(C#)ではあるものの、解説記事があるため読んでみると良いでしょう。

サムネイルC#で学ぶメソッドチェーン!利点や定義サンプルまで解説みなさんこんにちは! ガノーGanohrです! ≧▽≦最近Lancers経由のIT系記事の執筆やWordPressのカスタマイズや不具合対応の依頼が多く舞い込んでおり忙しい生活を送っております.しかしLancersではある建設業者を名乗る非常に悪質なクライアントにより脅迫被害が2か月以上続いており距離を置かなければ ... 続きを読むganohr.net2020-12-24

 

Promiseでは、処理成功後の処理をthenメソッドで、処理失敗時の処理(例外処理)をcatchメソッドで定義します。それぞれメソッドチェーンにより、繋げていくことで非同期処理の逐次処理を記述します。

メソッドチェーンを用いているため、いちいち非同期処理を行うインスタンスを指定する必要はありません。

JavaScriptのPromiseは成功時にresolveメソッドを実行し、失敗時にrejectメソッドを実行する

JavaScriptのPromiseは成功時・失敗時の呼び出しメソッドの概念写真
JavaScriptのPromiseは成功時にresolve関数を呼び出し、失敗時はreject関数を呼び出す

Promiseでは処理内部から引数で指定されたresolve(リゾルブ、解決)メソッドやreject(リジェクト、拒否)メソッドを呼び出すことで、処理を記述します。

この時resolveした場合thenメソッドで処理し、rejectした場合catchメソッドで処理(例外処理)していきます。

 

この対応をもとに、以下の引用コードをご覧ください。

JavaScriptのPromiseとは?入門用に分かりやすく解説! - Promiseの基本1 – 非同期処理の定義

// 処理1をp1として定義
const p1 = new Promise((resolve, reject)=>{
  //  : 何らかの処理
  resolve(“resolved!”); // 成功ならresolve関数を実行
 
  /*
  reject(“rejected!”); // 失敗ならreject関数を実行
  */
});
 
// 処理2をp2として定義
const p2 = new Promise(resolve=>{
  // 何らかの処理を実施
  // 失敗時に処理が不要ならrejectを省略可能
  resolve(“resolved!”);
});
 
// p1とp2の完了を待つ
Promise.all([p1,p2]).then(()=>{
  // p1とp2完了後の処理を記述
  return new Promise(resolve=>{
    // 何らかの処理を実施
    resolve(“resolved!”);
  });
});

 

ただし、Promiseでは複数の同期すべきオブジェクトがある場合に、メソッドチェーンのネストが問題となってしまいます。

 

JavaScriptのPromiseとは?入門用に分かりやすく解説! Capa.inc - Promiseの基本2 – 同期処理の定義

次に注目してほしいのがthen関数の戻り値が「return new Promise(~)」となっている点です。この記述を行うことで「then関数のネストが解消されている」点が重要です。

ここでいう「then関数のネスト」とは、以下のような記述方法です。

new Promise((resolve, reject)=>{
  resolve("A resolved!");
}).then(()=>{
  new Promise(resolve=>{
    resolve("B resolved!");
  }).then(()=>{
    new Promise(resolve=>{
      resolve("C resolved!");
    })
  })
});

これでは同期する処理が増えれば増えるほどネストが深くなっていき、コーディングの手間が増えてしまいます。また、ネストの深さが処理によって変わってしまうため、処理の順序を後から入れ替えることが難しくなってしまいます。

JavaScriptのPromiseは定義時即座に実行される

JavaScriptのPromiseの動作イメージ写真
JavaScriptのPromiseは定義と同時に動作を開始する

Promiseオブジェクトは生成時点に処理を定義しますが、その時点で処理が開始される点を忘れてはなりません。

要は、いちいち、startrunといったメソッドを呼び出す必要がないのです(そしてそのようなメソッドはありません)。

 

そもそも「開始タイミングを厳密に同期する必要性」は、基本的にありません。

しかし、実際に操作して動作するサンプルコードを作るうえでは、この制限への対処が必要です。そのため、そうしたコードが必要だといった無用な誤解を招かないよう、この前提を明示しました。

 

具体的にはPromiseに指定する処理内部からsetTimeout(~)を利用して、処理が継続するように定義していますが、それはサンプル用であるという前提を持っておくと理解しやすいでしょう。

JavaScriptのasync/awaitとは?

JavaScriptのasync/awaitが分からない女の子の写真(概念写真)
JavaScriptのasync/awaitとは何?

JavaScriptの‘async’(アシンク、アシンクロナイズド・asynchronizedの略、非同期の意味)や‘await’(アウェイト、待つの意味)は、Promiseをベースにより簡便な記述が可能な記述であり、ES2016より使用できます。

async function getX() {
  return 1;
}
async function getY() {
  throw "error";
}
async function main() {
  try {
    let x = await getX();
    console.log("x:" + x);
    let y = await getY();
    console.log("y:" + y);
  } catch(err) {
    console.log("err:" + err);
  }
}
//x:1
//err:error

JavaScriptのasyncとは?

asyncは「非同期処理を行う関数定義」と、「非同期処理を呼び出す関数定義」それぞれに付与するキーワードです。

 

async指定された関数は、まず戻り値としてPromiseオブジェクトを返却します。そのPromiseオブジェクト内部には、関数の内容が格納されており、即時実行されます。

この時、returnされた値がresolveされたものとして処理され、throw "エラーメッセージ"にて例外を投げるとそのメッセージがrejectされたものとして処理されます。

 

要は、asyncキーワードは、関数をPromise化する機能であると言えます。

なお、asyncが指定された関数の戻り値をPromiseオブジェクトにすることもできます。なぜならPromsieオブジェクトはPromsieオブジェクトが入れ子になっていても、問題なく処理できるからです。

 
ノート
なお、実際に調べてみるとasync指定した関数からPromiseオブジェクトを返却しても、Promiseオブジェクトが単に入れ子になっているのではなく、単一のPromiseオブジェクトが返却されていました。

JavaScriptのawaitとは?

awaitはasync指定された関数呼び出しの直前に指定するキーワードです。

 

awaitが指定された際の動作は、まず関数が完了(resolve)するまで待機し、完了時の値(resolveされた値)をセットします。

まとめ:JavaScriptのasync/awaitとPromiseの関係

JavaScriptのPromise・async/awaitまとめ(概念写真)
JavaScriptのPromiseとasync/awaitの関係をまとめましょう!

またasync指定された関数に対してawaitキーワードを使わずにアクセスした場合、Promsieオブジェクトが返却されます。

async function getA(){return 1}
async function getB(){return new Promise(resolve=>resolve(2))}
console.log(getA() instanceof Promise); // true
console.log(getB() instanceof Promise); // true
let a = getA(), b = await getB();
console.log(a); // Promise {<fulfilled>: 1}
console.log(b); // 2

 

この動作を紐解くと、JavaScriptのPromiseとasync/awaitの関係が見えてくるでしょう。

【JavaScriptのPromiseと、async/awaitの関係は?】

  • Promise → 非同期処理を実現するための機能である
  • async → 関数をPromiseオブジェクト化する機能である
  • await → Promiseオブジェクトがresolveされるのを待ち、実際に値を取り出す機能である

 

 

さて、次ページに実際に動かして学べるサンプルコードを用意しました。こちらはダウンロードも可能になっています。

WordPressの不具合対応/カスタマイズ¥15,000~

PC歴25年超、SE歴10年超、WordPress運営歴7年超、WordPressエンジニア歴5年超のスキルとノウハウを提供します

当サイト管理人の「ガノー」(Ganohr)は、日本最大手且つ東証一部上場企業が運営するクラウドソーシングサイト『Lancers』にて、認定ランサーとして活動しています。


※ 認定ランサーとはLancersにより様々な能力 ( 高い仕事遂行率・高い顧客満足度・多くの実績、など ) を評価したプロフェッショナルを認定する制度です。

 

JavaScriptカテゴリの最新記事