Promise について
■ Promise について
ECMAScript 6 世代の機能です。
■非同期実行の結果を受け取る
非同期実行の結果受け取りには、コールバック関数を使用します。
大抵の場合、ライブラリごとに、独自の仕様となります。
Promise を使用すると、結果受け取り方法を、統一できます。
■Promise の機能一覧
■コンストラクタ
コンストラクタ | 説明 |
Promise() | Promise オブジェクトを作成する(実行を開始する) |
■静的メソッド
メソッド | 説明 |
Promise.resolve() | Promise オブジェクトを作成する(必ず成功する) |
Promise.reject() | Promise オブジェクトを作成する(必ず失敗する) |
Promise.all() | 複数の実行結果をまとめて取得する |
Promise.race() | 最も先に完了した実行結果を1つ取得する |
■メソッド
実行を開始する
■ Promise オブジェクトを作成する(実行を開始する)
new 演算子を使って、Promise コンストラクタをインスタンス化します。
Promise オブジェクトを作成した瞬間から、非同期処理は開始されます。
new Promise( executor ) :Promise
第01引数 | Function | エグゼキューターに相当する関数を指定。 |
戻り値 | Promise | 新しい Promise オブジェクトが得られる。 |
■第01引数(エグゼキューター)
第01引数で指定する関数は、エグゼキューター(実行者)と呼ばれます。
この中で、好きな非同期処理を記述します。
エグゼキューターは、インスタンス化と同時に、即実行されます。
■エグゼキューターの仕様について
エグゼキューターの第01~02引数から、コールバック関数が得られます。
コールバック関数は、非同期実行に対応しています。
後から実行する事もできます。
最終的には、どちらか片方を、必ず呼び出す必要があります。
引数 | 説明 |
第01引数 | 実行結果が成功だった場合に呼び出す。 第01引数に、値情報(value)を渡す。 |
第02引数 | 実行結果が失敗だった場合に呼び出す。 第01引数に、失敗理由情報(reason)を渡す。 |
■戻り値(Promise)
実行結果を受け取る方法については、こちらで解説しています。
■使用例
Promise オブジェクトを作成する
// ------------------------------------------------------------
// エグゼキューター関数
// ------------------------------------------------------------
function ExecutorFunc( resolve , reject ){
console.log("非同期処理の開始");
// ------------------------------------------------------------
// 1 秒後に実行される関数
// ------------------------------------------------------------
setTimeout(function(){
if(1){
// 成功時
resolve("成功した");
}else{
// 失敗時
reject("失敗した");
}
console.log("非同期処理の完了");
} , 1000 * 1);
}
// ------------------------------------------------------------
// Promise オブジェクトを作成する(エグゼキューターの実行を開始する)
// ------------------------------------------------------------
var promise = new Promise(ExecutorFunc);
// 出力テスト
console.log(promise);
// ------------------------------------------------------------
// 実行結果を取得する
// ------------------------------------------------------------
promise.then(
// 成功時に呼び出される
function onFulfilled(value){
console.log(value);
},
// 失敗時に呼び出される
function onRejected(reason){
console.log(reason);
}
);
■ Promise オブジェクトを作成する(必ず成功する)
Promise.resolve() メソッドを使用します。
Promise.resolve( value ) :Promise
第01引数 | * | 値情報(value)を指定する。 |
戻り値 | Promise | 新しい Promise オブジェクトが得られる。 |
■戻り値(Promise)
実行結果を受け取る方法については、こちらで解説しています。
実行結果は、必ず成功となります。
第01引数で指定した、値情報(value)が得られます。
■使用例
必ず成功する Promise オブジェクトを作成する
// ------------------------------------------------------------
// 値情報(value)を用意
// ------------------------------------------------------------
var value = "成功テスト";
// ------------------------------------------------------------
// Promise オブジェクトを作成する(必ず成功する)
// ------------------------------------------------------------
var promise = Promise.resolve(value);
// 出力テスト
console.log(promise);
// ------------------------------------------------------------
// 実行結果を取得する
// ------------------------------------------------------------
promise.then(
// 成功時に呼び出される
function onFulfilled(value){
console.log(value); // "成功テスト"
},
// 失敗時に呼び出される
function onRejected(reason){
console.log(reason);
}
);
■ Promise オブジェクトを作成する(必ず失敗する)
Promise.reject() メソッドを使用します。
Promise.reject( reason ) :Promise
第01引数 | * | 失敗理由情報(reason)を指定する。 |
戻り値 | Promise | 新しい Promise オブジェクトが得られる。 |
■戻り値(Promise)
実行結果を受け取る方法については、こちらで解説しています。
実行結果は、必ず失敗となります。
第01引数で指定した、失敗理由情報(reason)が得られます。
■使用例
必ず失敗する Promise オブジェクトを作成する
// ------------------------------------------------------------
// 失敗理由情報(reason)を用意
// ------------------------------------------------------------
var reason = new Error("失敗テスト");
// ------------------------------------------------------------
// Promise オブジェクトを作成する(必ず失敗する)
// ------------------------------------------------------------
var promise = Promise.reject(reason);
// 出力テスト
console.log(promise);
// ------------------------------------------------------------
// 実行結果を取得する
// ------------------------------------------------------------
promise.then(
// 成功時に呼び出される
function onFulfilled(value){
console.log(value);
},
// 失敗時に呼び出される
function onRejected(reason){
console.log(reason); // "失敗テスト"
}
);
■「Thenable なオブジェクト」から、Promise オブジェクトを作成する
Promise.resolve() メソッドを使用します。
引数に、「Thenable なオブジェクト」を指定します。
Promise.resolve( thenable ) :Promise
第01引数 | Object | Thenable なオブジェクトを指定する(then メソッドを持つオブジェクト) |
戻り値 | Promise | 新しい Promise オブジェクトが得られる。 |
■「Thenable なオブジェクト」とは?
then() メソッドを実装しているオブジェクトです。
■ then() メソッドの仕様について
第01~02引数から、コールバック関数が得られます。
コールバック関数は、非同期実行に対応しています。
後から実行する事もできます。
最終的には、どちらか片方を、必ず呼び出す必要があります。
引数 | 説明 |
第01引数 | 実行結果が成功だった場合に呼び出す。 第01引数に、値情報(value)を渡す。 |
第02引数 | 実行結果が失敗だった場合に呼び出す。 第01引数に、失敗理由(reason)を渡す。 |
■戻り値(Promise)
実行結果を受け取る方法については、こちらで解説しています。
■使用例
「Thenable なオブジェクト」から、Promise オブジェクトを作成する
// ------------------------------------------------------------
// 「Thenable なオブジェクト」を用意する
// ------------------------------------------------------------
var thenable_obj = {
// ------------------------------------------------------------
// then メソッドを実装する
// ------------------------------------------------------------
then:function (resolve , reject){
if(1){
// 成功時
resolve("成功した");
}else{
// 失敗時
reject("失敗した");
}
}
};
// ------------------------------------------------------------
// 「Thenable なオブジェクト」から、Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve(thenable_obj);
// 出力テスト
console.log(promise);
「Thenable なオブジェクト」から、Promise オブジェクトを作成し、結果を受け取る
// ------------------------------------------------------------
// ThenableObj コンストラクタ(Thenable の仕様に対応している)
// ------------------------------------------------------------
function ThenableObj(){
var self = this;
// ------------------------------------------------------------
// ローカル変数
// ------------------------------------------------------------
var then_arguments = null;
var receive_obj = null;
// ------------------------------------------------------------
// then メソッドを実装する
// ------------------------------------------------------------
self.then = function ( resolve , reject ){
// Arguments オブジェクトを取得
then_arguments = arguments;
// 返信を試みる
receive();
};
// ------------------------------------------------------------
// 返信を試みる関数
// ------------------------------------------------------------
function receive(){
if(!then_arguments) return;
if(!receive_obj) return;
// 各コールバック関数を取得
var resolve = then_arguments[0];
var reject = then_arguments[1];
// 成功時
if(receive_obj.result){
if(!resolve) return;
resolve(receive_obj.value);
// 失敗時
}else{
if(!reject) return;
reject(receive_obj.reason);
}
}
// ------------------------------------------------------------
// 非同期処理の実行を開始
// ------------------------------------------------------------
(function(){
// ------------------------------------------------------------
// 1 秒後に実行される関数
// ------------------------------------------------------------
setTimeout(function(){
// ------------------------------------------------------------
// 返信オブジェクトを作成
// ------------------------------------------------------------
receive_obj = new Object();
if(1){
receive_obj.result = true;
receive_obj.value = "成功した";
}else{
receive_obj.result = false;
receive_obj.reason = new Error("失敗した");
}
// ------------------------------------------------------------
// 返信を試みる
// ------------------------------------------------------------
receive();
} , 1000 * 1);
})();
}
// ------------------------------------------------------------
// ThenableObj オブジェクトを作成する
// ------------------------------------------------------------
var thenable_obj0 = new ThenableObj();
// ------------------------------------------------------------
// 実行結果を取得する
// ------------------------------------------------------------
thenable_obj0.then(
// 成功時に呼び出される
function onFulfilled(value){
console.log(value);
},
// 失敗時に呼び出される
function onRejected(reason){
console.log(reason);
}
);
// ------------------------------------------------------------
// ThenableObj オブジェクトを作成する
// ------------------------------------------------------------
var thenable_obj1 = new ThenableObj();
// ------------------------------------------------------------
// 「Thenable なオブジェクト」から、Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve(thenable_obj1);
// ------------------------------------------------------------
// 実行結果を取得する(純粋な Promise なので、この後 Promise チェーンなども利用できる)
// ------------------------------------------------------------
promise.then(
// 成功時に呼び出される
function onFulfilled(value){
console.log(value);
},
// 失敗時に呼び出される
function onRejected(reason){
console.log(reason);
}
);
実行結果を取得する
■実行結果を取得する(成功と失敗)
then() メソッドを使用します。
このメソッドは、非同期実行です。
結果を受け取るには、引数にコールバック関数を指定します。
Promise.then( onFulfilled , onRejected ) :Promise
第01引数 | Function | 成功時に呼び出されるコールバック関数を指定する。 |
第02引数(略可) | Function | 失敗時に呼び出されるコールバック関数を指定する。 |
戻り値 | Promise | 新しい Promise オブジェクトが得られる。 |
■第01引数(onFulfilled)
成功時に呼び出されるコールバック関数を指定します。
コールバック関数の仕様は、以下の通りです。
第01引数から、値情報(value)を受け取れます。
戻り値から、好きな Promise オブジェクトを返す事もできます。
これは、Promise チェーンで使用します。
■第02引数(onRejected)
失敗時に呼び出されるコールバック関数を指定します。
コールバック関数の仕様は、以下の通りです。
第01引数から、失敗理由情報(reason)を受け取れます。
戻り値から、好きな Promise オブジェクトを返す事もできます。
これは、Promise チェーンで使用します。
■戻り値(Promise)
新しい Promise オブジェクトが得られます。
これは、Promise チェーンで使用します。
■使用例
エグゼキューターの実行結果を取得する
// ------------------------------------------------------------
// エグゼキューター関数
// ------------------------------------------------------------
function ExecutorFunc( resolve , reject ){
if(1){
// 成功時
resolve("成功した");
}else{
// 失敗時
reject("失敗した");
}
}
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = new Promise(ExecutorFunc);
// ------------------------------------------------------------
// 成功時に呼び出される関数
// ------------------------------------------------------------
function FulfilledFunc (value){
console.log(value);
}
// ------------------------------------------------------------
// 失敗時に呼び出される関数
// ------------------------------------------------------------
function RejectedFunc (reason){
console.log(reason);
}
// ------------------------------------------------------------
// 実行結果を取得する
// ------------------------------------------------------------
promise.then( FulfilledFunc , RejectedFunc);
「ロード済みイメージ要素」の作成を開始し、結果を取得する
// ------------------------------------------------------------
// 「ロード済みイメージ要素」を作成する関数
// ------------------------------------------------------------
function ImageElement_CreateAndLoad( url ){
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = new Promise(function(resolve,reject){
// イメージ要素を作成
var image = new Image();
// 読み込み成功時に実行されるイベント
image.onload = function(){
resolve(image);
}
// 読み込み失敗時に実行されるイベント
image.onerror = function(){
reject(new Error("Not Found"));
}
// URL を指定して、読み込みを開始する
image.src = url;
});
// ------------------------------------------------------------
// Promise オブジェクトを返す
// ------------------------------------------------------------
return promise;
}
// ------------------------------------------------------------
// 「ロード済みイメージ要素」の作成を開始する
// ------------------------------------------------------------
var promise = ImageElement_CreateAndLoad( "http://example.com/graphics/texture_00.png" );
// ------------------------------------------------------------
// 実行結果を取得する
// ------------------------------------------------------------
promise.then(
// 成功時に呼び出される
function onFulfilled(value){
console.log(value);
},
// 失敗時に呼び出される
function onRejected(reason){
console.log(reason);
}
);
■実行結果を取得する(失敗のみ)
catch() メソッドを使用します。
このメソッドは、非同期実行です。
結果を受け取るには、引数にコールバック関数を指定します。
Promise.catch( onRejected ) :Promise
第01引数 | Function | 失敗時に呼び出されるコールバック関数を指定する。 |
戻り値 | Promise | 新しい Promise オブジェクトが得られる。 |
■第01引数(onRejected)
失敗時に呼び出されるコールバック関数を指定します。
コールバック関数の仕様は、以下の通りです。
第01引数から、失敗理由情報(reason)を受け取れます。
戻り値から、好きな Promise オブジェクトを返す事もできます。
これは、Promise チェーンで使用します。
■戻り値(Promise)
新しい Promise オブジェクトが得られます。
これは、Promise チェーンで使用します。
■使用例
エグゼキューターの実行結果を取得する
// ------------------------------------------------------------
// エグゼキューター関数
// ------------------------------------------------------------
function ExecutorFunc( resolve , reject ){
if(0){
// 成功時
resolve("成功した");
}else{
// 失敗時
reject("失敗した");
}
}
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = new Promise(ExecutorFunc);
// ------------------------------------------------------------
// 失敗時に呼び出される関数
// ------------------------------------------------------------
function RejectedFunc (reason){
console.log(reason);
}
// ------------------------------------------------------------
// 実行結果を取得する(失敗のみ)
// ------------------------------------------------------------
promise.catch(RejectedFunc);
「ロード済みイメージ要素」の作成を開始し、結果を取得する
// ------------------------------------------------------------
// 「ロード済みイメージ要素」を作成する関数
// ------------------------------------------------------------
function ImageElement_CreateAndLoad( url ){
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = new Promise(function(resolve,reject){
// イメージ要素を作成
var image = new Image();
// 読み込み成功時に実行されるイベント
image.onload = function(){
resolve(image);
}
// 読み込み失敗時に実行されるイベント
image.onerror = function(){
reject(new Error("Not Found"));
}
// URL を指定して、読み込みを開始する
image.src = url;
});
// ------------------------------------------------------------
// Promise オブジェクトを返す
// ------------------------------------------------------------
return promise;
}
// ------------------------------------------------------------
// 「ロード済みイメージ要素」の作成を開始する
// ------------------------------------------------------------
var promise = ImageElement_CreateAndLoad( "http://example.com/graphics/texture_00.png" );
// ------------------------------------------------------------
// 実行結果を取得する(成功のみ)
// ------------------------------------------------------------
promise = promise.then(function (value){
console.log(value);
});
// ------------------------------------------------------------
// 実行結果を取得する(失敗のみ)
// ------------------------------------------------------------
promise = promise.catch(function (reason){
console.log(reason);
});
■複数の実行結果をまとめて取得する
Promise.all() メソッドを使用します。
Promise.all( promiseArray ) :Promise
第01引数 | Array | Promise のリストを指定する。 |
戻り値 | Promise | 新しい Promise オブジェクトが得られる。 |
■戻り値(Promise)
新しい Promise オブジェクトが得られます。
結果を受け取るには、さらに then() メソッドを呼び出します。
すべての結果は、配列に格納されています。
結果の格納順序は、Promise.all() の第01引数の順序と同じです。
■非同期処理の並列実行に注意
結果を取得したい Promise オブジェクトは、すべて事前に作成しておく必要があります。
1つずつ順番に実行したい場合は、Promise チェーンを利用します。
■使用例
複数の実行結果をまとめて取得する
// ------------------------------------------------------------
// 「指定時間後」に「指定結果」が得られる関数
// ------------------------------------------------------------
function PromiseCreateFunc( value , time ){
// Promise オブジェクトを作成する
var promise = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(value);
} , time);
});
// Promise オブジェクトを返す
return promise;
}
// ------------------------------------------------------------
// 複数の Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise0 = PromiseCreateFunc( "aaaaa" , 3000 );
var promise1 = PromiseCreateFunc( "bbbbb" , 1000 );
var promise2 = PromiseCreateFunc( "ccccc" , 2000 );
// ------------------------------------------------------------
// 「複数の実行結果」の取得を開始する
// ------------------------------------------------------------
var promise = Promise.all( [promise0 , promise1 , promise2] );
// ------------------------------------------------------------
// 「複数の実行結果」を取得する
// ------------------------------------------------------------
promise.then(
// 成功時に呼び出される
function onFulfilled(value){
console.log(value); // [ "aaaaa" , "bbbbb" , "ccccc" ]
},
// 失敗時に呼び出される
function onRejected(reason){
console.log(reason);
}
);
■最も先に完了した実行結果を1つ取得する
Promise.race() メソッドを使用します。
Promise.race( promiseArray ) :Promise
第01引数 | Array | Promise のリストを指定する。 |
戻り値 | Promise | 新しい Promise オブジェクトが得られる。 |
■戻り値(Promise)
新しい Promise オブジェクトが得られます。
結果を受け取るには、さらに then() メソッドを呼び出します。
最も先に完了した実行結果を、1つだけ取得できます。
複数が完了済みだった場合、Promise.race() の第01引数の昇順で評価されます。
■キャンセルについて
Promise 自体には、キャンセルに対応する仕様はありません。
すべての非同期処理は、最後まで実行されます。
■使用例
最も先に完了した実行結果を1つ取得する
// ------------------------------------------------------------
// 「指定時間後」に「指定結果」が得られる関数
// ------------------------------------------------------------
function PromiseCreateFunc( value , time ){
// Promise オブジェクトを作成する
var promise = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(value);
} , time);
});
// Promise オブジェクトを返す
return promise;
}
// ------------------------------------------------------------
// 複数の Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise0 = PromiseCreateFunc( "aaaaa" , 3000 );
var promise1 = PromiseCreateFunc( "bbbbb" , 1000 );
var promise2 = PromiseCreateFunc( "ccccc" , 2000 );
// ------------------------------------------------------------
// 「最も先に完了した実行結果」の取得を開始する
// ------------------------------------------------------------
var promise = Promise.race( [promise0 , promise1 , promise2] );
// ------------------------------------------------------------
// 「最も先に完了した実行結果」を取得する
// ------------------------------------------------------------
promise.then(
// 成功時に呼び出される
function onFulfilled(value){
console.log(value); // "bbbbb"
},
// 失敗時に呼び出される
function onRejected(reason){
console.log(reason);
}
);
Promise チェーンについて
■ Promise のメソッドチェーンについて
■対応メソッド
以下のメソッドは、メソッドチェーンに対応しています。
■メソッドチェーンを利用した場合
メソッドチェーンを利用すると、コールバック関数を接続する事ができます。
数珠つなぎにして、複数のコールバック関数を連結する事ができます。
接続したコールバック関数は、順序通りに実行されます。
■使用例
複数のコールバック関数を接続し、実行順序を確認する(メソッドチェーン表記)
// ------------------------------------------------------------
// ExecA 関数
// ------------------------------------------------------------
function ExecA( value ){
console.log("--- ExecA ---");
}
// ------------------------------------------------------------
// ExecB 関数
// ------------------------------------------------------------
function ExecB( value ){
console.log("--- ExecB ---");
}
// ------------------------------------------------------------
// ExecC 関数
// ------------------------------------------------------------
function ExecC( value ){
console.log("--- ExecC ---");
}
// ------------------------------------------------------------
// ExecD 関数
// ------------------------------------------------------------
function ExecD( value ){
console.log("--- ExecD ---");
}
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve();
// ------------------------------------------------------------
// メソッドチェーンを使って、コールバック関数を接続する
// ------------------------------------------------------------
promise.then(ExecA).then(ExecB).then(ExecC).then(ExecD);
複数のコールバック関数を接続し、実行順序を確認する
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve("start");
// ------------------------------------------------------------
// コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecA ---");
});
// ------------------------------------------------------------
// コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecB ---");
});
// ------------------------------------------------------------
// コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecC ---");
});
// ------------------------------------------------------------
// コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecD ---");
});
■コールバック関数の戻り値と、新しい結果について
■チェーン対応メソッドの戻り値について
新しい Promise オブジェクトが得られます。
新しい Promise オブジェクトから、then() メソッドを呼び出します。
第01引数から、次に実行したいコールバック関数を指定できます。
登録したコールバック関数からは、新しい結果を受け取れます。
■コールバック関数の戻り値について
好きな Promise オブジェクトを返す事ができます。
ここで返した Promise オブジェクトは、次回の結果となります。
■コールバック関数の引数について
コールバック関数の第01引数から、今回の結果が得られます。
前回のコールバック関数の戻り値が、今回の結果となります。
■使用例
コールバック関数の戻り値と、新しい結果を確認する(メソッドチェーン表記)
// ------------------------------------------------------------
// ExecA 関数
// ------------------------------------------------------------
function ExecA( value ){
console.log("--- ExecA ---");
// 「今回の結果」を取得
console.log(value); // "start"
// 「次回の結果」を返す
var promise = Promise.resolve("aaaaa");
return promise;
}
// ------------------------------------------------------------
// ExecB 関数
// ------------------------------------------------------------
function ExecB( value ){
console.log("--- ExecB ---");
// 「今回の結果」を取得
console.log(value); // "aaaaa"
// 「次回の結果」を返す
var promise = Promise.resolve("bbbbb");
return promise;
}
// ------------------------------------------------------------
// ExecC 関数
// ------------------------------------------------------------
function ExecC( value ){
console.log("--- ExecC ---");
// 「今回の結果」を取得
console.log(value); // "bbbbb"
// 「次回の結果」を返す
var promise = Promise.resolve("ccccc");
return promise;
}
// ------------------------------------------------------------
// ExecD 関数
// ------------------------------------------------------------
function ExecD( value ){
console.log("--- ExecD ---");
// 「今回の結果」を取得
console.log(value); // "ccccc"
}
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve("start");
// ------------------------------------------------------------
// メソッドチェーンを使って、コールバック関数を接続する
// ------------------------------------------------------------
promise.then(ExecA).then(ExecB).then(ExecC).then(ExecD);
コールバック関数の戻り値と、新しい結果を確認する
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve("start");
// ------------------------------------------------------------
// コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecA ---");
// 「今回の結果」を取得
console.log(value); // "start"
// 「次回の結果」を返す
var promise = Promise.resolve("aaaaa");
return promise;
});
// ------------------------------------------------------------
// コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecB ---");
// 「今回の結果」を取得
console.log(value); // "aaaaa"
// 「次回の結果」を返す
var promise = Promise.resolve("bbbbb");
return promise;
});
// ------------------------------------------------------------
// コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecC ---");
// 「今回の結果」を取得
console.log(value); // "bbbbb"
// 「次回の結果」を返す
var promise = Promise.resolve("ccccc");
return promise;
});
// ------------------------------------------------------------
// コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecD ---");
// 「今回の結果」を取得
console.log(value); // "ccccc"
});
■次回の結果を必ず成功させるには
■必ず成功する Promise オブジェクトを作成する
Promise.resolve() メソッドを使用します。
この Promise オブジェクトを、コールバック関数から返します。
この場合、次回の結果は、必ず成功します。
■コールバック関数から、任意の値を返した場合
この場合、次回の結果は、必ず成功します。
■次回の結果を必ず失敗させるには
■必ず失敗する Promise オブジェクトを作成する
Promise.reject() メソッドを使用します。
この Promise オブジェクトを、コールバック関数から返します。
この場合、次回の結果は、必ず失敗します。
■コールバック関数内でエラーが発生した場合
コールバック関数内で、エラーを発生させます。
この場合、次回の結果は、必ず失敗します。
■失敗やエラーを、まとめてキャッチする
catch() メソッドを使用します。
Promise チェーン内で発生した、失敗やエラーなどを、まとめて捕捉できます。
■使用例
失敗やエラーを、まとめてキャッチする(メソッドチェーン表記)
// ------------------------------------------------------------
// ExecA 関数
// ------------------------------------------------------------
function ExecA( value ){
console.log("--- ExecA ---");
// 「次回の結果」は必ず成功
var promise = Promise.resolve("aaaaa");
return promise;
}
// ------------------------------------------------------------
// ExecB 関数
// ------------------------------------------------------------
function ExecB( value ){
console.log("--- ExecB ---");
if(0){
// 「次回の結果」は必ず成功
var promise = Promise.resolve("bbbbb");
return promise;
}else{
// 「次回の結果」は必ず失敗
var promise = Promise.reject(new Error("失敗テスト"));
return promise;
}
}
// ------------------------------------------------------------
// ExecC 関数
// ------------------------------------------------------------
function ExecC( value ){
console.log("--- ExecC ---");
}
// ------------------------------------------------------------
// ErrorCatchFunc 関数
// ------------------------------------------------------------
function ErrorCatchFunc( reason ){
// 失敗理由情報を取得
console.log(reason);
}
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve("start");
// ------------------------------------------------------------
// メソッドチェーンを使って、コールバック関数を接続する
// ------------------------------------------------------------
promise.then(ExecA).then(ExecB).then(ExecC).catch(ErrorCatchFunc);
失敗やエラーを、まとめてキャッチする
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve("start");
// ------------------------------------------------------------
// 成功コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecA ---");
// 「次回の結果」は必ず成功
var promise = Promise.resolve("aaaaa");
return promise;
});
// ------------------------------------------------------------
// 成功コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecB ---");
if(0){
// 「次回の結果」は必ず成功
var promise = Promise.resolve("bbbbb");
return promise;
}else{
// 「次回の結果」は必ず失敗
var promise = Promise.reject(new Error("失敗テスト"));
return promise;
}
});
// ------------------------------------------------------------
// 成功コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log("--- ExecC ---");
});
// ------------------------------------------------------------
// 失敗コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.catch( function (reason){
// 失敗理由情報を取得
console.log(reason);
});
■ Promise チェーンの非同期実行について
■ Promise の同期実行に注意
あたかも非同期動作しそうですが、Promise 自体は同期実行です。
setTimeout() のような、遅延実行を行う事はありません。
対応可能なキューが貯まっている場合、一度にすべての消化を試みます。
この間、ブラウザは応答不能に陥ります。
■ Promise を非同期実行化するには?
エグゼキューター付きの Promise オブジェクトを生成します。
エグゼキューター関数内にて、好きな非同期 API を利用します。
非同期 API を利用しなかった場合、Promise は同期実行となります。
この Promise オブジェクトを、コールバック関数から返します。
■使用例
Promise チェーンを遅延実行する
// ------------------------------------------------------------
// 「指定時間後」に「指定結果」が得られる関数
// ------------------------------------------------------------
function PromiseCreateFunc( value , time ){
// Promise オブジェクトを作成する
var promise = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(value);
} , time);
});
// Promise オブジェクトを返す
return promise;
}
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve(0);
(function(){
var i = 0;
var num = 10000;
for(i=0;i < num;i++){
// ------------------------------------------------------------
// コールバック関数を接続する
// ------------------------------------------------------------
promise = promise.then( function (value){
if((value % 100) == 0) console.log(value);
// 新しい Promise オブジェクトを作成する(非同期動作)
var promise = PromiseCreateFunc( (value + 1) , 1 );
return promise;
});
}
})();
// ------------------------------------------------------------
// コールバック関数を接続する(最後に動作)
// ------------------------------------------------------------
promise = promise.then( function (){
console.timeEnd("test");
});
console.time("test");
■複数の Promise を1つずつ順番に実行する
■非同期処理の開始タイミングについて
Promise オブジェクトを作成すると、非同期処理も開始されます。
よって事前に、Promise オブジェクトを生成しておく事はできません。
■直列的に1つずつ実行するには?
コールバック関数内にて、Promise オブジェクトを作成します。
この Promise オブジェクトを、コールバック関数から返します。
■使用例
Promise チェーンを使って、1つずつ順番に実行する
// ------------------------------------------------------------
// 「指定時間後」に「指定結果」が得られる関数
// ------------------------------------------------------------
function PromiseCreateFunc( value , time ){
// Promise オブジェクトを作成する
var promise = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(value);
} , time);
});
// Promise オブジェクトを返す
return promise;
}
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve();
// ------------------------------------------------------------
// 成功時に呼び出される関数を接続
// ------------------------------------------------------------
promise = promise.then( function (value){
// 「非同期処理」を開始する
var promise = PromiseCreateFunc( "aaaaa" , 1000 );
// 「次回の結果」を返す
return promise;
});
// ------------------------------------------------------------
// 成功時に呼び出される関数を接続
// ------------------------------------------------------------
promise = promise.then( function (value){
// 「今回の結果」を取得
console.log(value); // "aaaaa"
// 「非同期処理」を開始する
var promise = PromiseCreateFunc( "bbbbb" , 1000 );
// 「次回の結果」を返す
return promise;
});
// ------------------------------------------------------------
// 成功時に呼び出される関数を接続
// ------------------------------------------------------------
promise = promise.then( function (value){
// 「今回の結果」を取得
console.log(value); // "bbbbb"
// 「非同期処理」を開始する
var promise = PromiseCreateFunc( "ccccc" , 1000 );
// 「次回の結果」を返す
return promise;
});
// ------------------------------------------------------------
// 成功時に呼び出される関数を接続
// ------------------------------------------------------------
promise = promise.then( function (value){
// 「今回の結果」を取得
console.log(value); // "ccccc"
});
// ------------------------------------------------------------
// 失敗時に呼び出される関数を接続(Promise チェーン内で発生したエラーをキャッチ)
// ------------------------------------------------------------
promise = promise.catch( function (reason){
console.log(reason);
});
Promise チェーンに割り込んで、コールバック関数を繰り返し実行する
// ------------------------------------------------------------
// 「ロード済みイメージ要素」を作成する関数
// ------------------------------------------------------------
function ImageElement_CreateAndLoad( url ){
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = new Promise(function(resolve,reject){
// イメージ要素を作成
var image = new Image();
// 読み込み成功時に実行されるイベント
image.onload = function(){
resolve(image);
}
// 読み込み失敗時に実行されるイベント
image.onerror = function(){
reject(new Error("Not Found"));
}
// URL を指定して、読み込みを開始する
image.src = url;
});
// ------------------------------------------------------------
// Promise オブジェクトを返す
// ------------------------------------------------------------
return promise;
}
// ------------------------------------------------------------
// Promise オブジェクトを作成する
// ------------------------------------------------------------
var promise = Promise.resolve();
(function(){
// ------------------------------------------------------------
// URL リスト
// ------------------------------------------------------------
var url_list = [
"http://example.com/graphics/texture_00.png",
"http://example.com/graphics/texture_01.png",
"http://example.com/graphics/texture_02.png",
"http://example.com/graphics/texture_03.png",
"http://example.com/graphics/texture_04.png"
];
// 値情報リスト
var value_list = new Array();
var i = 0;
var num = url_list.length;
// ------------------------------------------------------------
// 成功時に呼び出される関数を接続(繰り返し実行)
// ------------------------------------------------------------
promise = promise.then(function execute(value){
// 値情報リストに追加
if(value) value_list.push(value);
// 繰り返し終了
if(i >= num) return value_list;
// ------------------------------------------------------------
// 「ロード済みイメージ要素」の作成を開始する
// ------------------------------------------------------------
var promise = ImageElement_CreateAndLoad( url_list[i] );
i += 1;
// ------------------------------------------------------------
// 成功時に呼び出される関数を接続(Promise チェーンに割り込む)
// ------------------------------------------------------------
promise = promise.then(execute);
return promise;
});
})();
// ------------------------------------------------------------
// 成功時に呼び出される関数を接続(最後まで完了した場合)
// ------------------------------------------------------------
promise = promise.then( function (value){
console.log(value);
});
// ------------------------------------------------------------
// 失敗時に呼び出される関数を接続(Promise チェーン内で発生したエラーをキャッチ)
// ------------------------------------------------------------
promise = promise.catch( function (reason){
console.log(reason);
});