JavaScript(ES6)のPromiseを試してみる その1

すっかりご無沙汰してます。 元岡です。

前回はジェネレータについて紹介させて頂きました。

引き続き、コールバックや非同期関係の記事を書いて行く予定です。

今回は、ジェネレータと同じくES6から実装されたPromiseの方も試してみます。

と、その前に…

今年の6月に公開予定の ES2017 には、5つの新仕様が入ります。

  • Object.values / Object.entries
  • String padding
  • Object.getOwnPropertyDescriptors
  • Trailing commas in function parameter lists and calls
  • Async Functions

どの機能もとても待ち望んでいたものですが、その中でも ES6(ES2015) から先延ばしされていた Async Functions ではないでしょうか。

Async Functionsは、非同期処理をより同期的に記述する事が出来る新文法です。

こちらについてはまた改めて記事にさせて頂きたいと思いますが、非同期処理を同期的に処理する際に await を使うのですが、ここで呼び出す非同期処理はPromiseをラップして返す事になります。 Async Functionsを使いこなすには必然とPromiseについて知っておく必要があります。

ではPromiseについて調べてみます。

Promiseについて

Promiseは非同期の処理をスタイリッシュに記述する事が出来る機能です。 同じ機能として有名なのは、JQueryDeferredではないでしょうか。

以下、コードの流れです。

  • Promiseオブジェクトを生成する。
  • Promiseオブジェクトに対して、thenメソッド / catchメソッド で非同期処理が成功または失敗した時のコールバックを登録する。
  • 非同期処理が終了したら、その結果を resolve(成功)メソッド / reject(失敗)メソッドで通知する。
  • 通知を受け取ったPromiseオブジェクトは、登録されていたコールバックが呼ばれる。

結果を処理するthenメソッドは、さらにPromiseオブジェクトを返してメソッドチェーンする事で、非同期処理を直列に処理できます。 また、Promise.all メソッドに、複数のPromiseオブジェクトを渡す事で、非同期処理を並列に処理する事ができます。

これにより非同期処理のコールバックでネストが深くなってしまう、いわゆる コールバック地獄 を解消することが出来ます!

では、実際に試してみましょう。 比較のためJQueryDeferred も書いてみますね。

Promiseの場合

(function(){
   //Promiseオブジェクトを返す
   return new Promise(function(resolve, reject){
      //非同期処理(setTimeoutでエミュレート)
      setTimeout(function(){
         //非同期処理の成功/失敗を乱数で決める
         var bool = Math.random() * 2;
         if (bool>1) {
            resolve("成功");
         } else {
            reject("失敗");
         }
      }, 3000);
   });
})().then(function(result){
      //成功時
      console.log("then:"+result);
   }).catch(function(result){
      //失敗時
      console.log("catch:"+result);
   });
実行結果
(3秒後に以下が表示)
> then:成功 
または
> catch:失敗

Deferredの場合

(function(){
   var deferred = new $.Deferred();
   //非同期処理(setTimeoutでエミュレート)
   setTimeout(function(){
      //非同期処理の成功/失敗を乱数で決める
      var bool = Math.random() * 2;
      if (bool>1) {
         deferred.resolve("成功");
         } else {
         deferred.reject("失敗");
         }
      }, 3000);
   });
   //Promiseオブジェクトを返す
   return deferred.promise();
})().done(function(result){
      //成功時
      console.log("done:"+result);
   }).fail(function(result){
      //成功時
      console.log("fail:"+result);
   });
実行結果
> done:成功 
または
> fail:失敗

上記コードを実行すると3秒にログが表示されます。

各メソッドを補足しますと、Promiseのthenメソッドは、第二引数にエラー時のコールバックを書く事ができます。

またcatchメソッドは、Promise内の処理、例外エラーが発生した場合も受け取る事ができます。 例外エラーをハンドリングする際にわざわざ try catch文を書かなくて済みますね。

さて、実際に動かしてみていかがだったでしょうか? コードは少し複雑で多少慣れが必要ですが、慣れてしまえば簡単に記述できそうですね!

次回は、Promiseを使って非同期処理を直列に行う処理を試してみたいと思います。

それでは、また!