すっかりご無沙汰してます。 元岡です。
前回はジェネレータについて紹介させて頂きました。
引き続き、コールバックや非同期関係の記事を書いて行く予定です。
今回は、ジェネレータと同じく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は非同期の処理をスタイリッシュに記述する事が出来る機能です。 同じ機能として有名なのは、JQueryのDeferredではないでしょうか。
以下、コードの流れです。
- Promiseオブジェクトを生成する。
- Promiseオブジェクトに対して、thenメソッド / catchメソッド で非同期処理が成功または失敗した時のコールバックを登録する。
- 非同期処理が終了したら、その結果を resolve(成功)メソッド / reject(失敗)メソッドで通知する。
- 通知を受け取ったPromiseオブジェクトは、登録されていたコールバックが呼ばれる。
結果を処理するthenメソッドは、さらにPromiseオブジェクトを返してメソッドチェーンする事で、非同期処理を直列に処理できます。 また、Promise.all メソッドに、複数のPromiseオブジェクトを渡す事で、非同期処理を並列に処理する事ができます。
これにより非同期処理のコールバックでネストが深くなってしまう、いわゆる コールバック地獄 を解消することが出来ます!
では、実際に試してみましょう。 比較のためJQueryのDeferred も書いてみますね。
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を使って非同期処理を直列に行う処理を試してみたいと思います。
それでは、また!