9) アンチパターン
Promiseオブジェクトをだいぶ理解いただけたでしょうか。 次はついうっかり使ってしまいがちなアンチパターンを紹介します。
ここで紹介するものは以下のパターンを参考にした ES6 Promise版です。
Promise Anti-patterns
http://taoofcode.net/promise-anti-patterns/
Nested Promises
taskA().then(function(taskAResult){
taskB().then(function(taskBResult){
taskC().then(function(taskCResult){
doSomething(taskAResult, taskBResult, taskCResult);
});
});
});
- 返却された値を全て知るために
then()
がネストしています
fix
all()
を使えば返却された値を全て知る事ができます。
Promise.all([taskA(),taskB(),taskC()])
.then(function(values){
doSomething(values);
})
;
The Broken Chain
function getPromise(){
return new Promise(function(resolve,reject){
resolve(1);
});
}
function callPromise(){
var promise = getPromise();
promise.then(function(){ doSomething(); });
return promise;
}
var result = callPromise();
then()
で返却されたPromiseオブジェクトが使用されないためメソッドチェインが途切れています- このため
doSomething()
で発生したエラーをハンドリングできません
fix
then()
の結果を返却すると、呼び出し側でthen()
のメソッドチェインをつなげる事ができます。
function callPromise(){
var promise = getPromise();
return promise.then(function(){
// ...
});
}
callPromise().then(function(){
console.info('fulfilled');
});
The Collection Kerfuffle
function task(value){
return new Promise(function(resolve,reject){
resolve(value);
});
}
var numbers = [1,2,3];
var results = [];
function recursive(index){
if (index >= numbers.length) {
return;
}
task(numbers[index])
.then(function(result){
results.push(result);
recursive(index + 1);
})
;
}
recursive(0);
- 再帰処理が目的を分かりづらくさせています
fix
all()
が複数のPromiseオブジェクトを並列で実行できる事を思い出しましょう。
function task(value){
return new Promise(function(resolve,reject){
resolve(value);
});
}
var numbers = [1,2,3];
var results = [];
var tasks = numbers.map(function(number){
return task(number);
});
Promise.all(tasks)
.then(function(values){
results = values;
})
;
逐次実行したい場合はreduce()
を使いましょう。
var tasks = values.map(function(value){
return task(value).then(function(value){
results.push(value);
});
});
var reduced = tasks.reduce(function(promise, task){
return promise.then(task);
}, Promise.resolve());
reduced.then(function(){
console.log(results);
});
The Overly Keen Error Handler
task().then(function(){
throw new Error('unexpected');
},function(error){
console.log(error.message);
});
then(onFulfilled, onRejected)
はonFulfilled
内のエラーをハンドリングできません
fix
エラーをハンドリングするには一番最後のthen()
でonRejected
だけ指定します。
task()
.then()
.then(null, function(){
console.log(error.message);
})
;
またはcatch()
を使います。
task()
.then()
.catch(function(error){
console.log(error.message);
})
;
The Forgotten Promise
Promise.resolve()
.then(function(){
return new Promise(function(resolve){
resolve(1);
});
})
.then(function(){
return new Promise(function(resolve){
resolve(2);
});
})
;
then()
はPromiseオブジェクトを生成して返すため、自分でPromiseオブジェクトを生成する必要はありません
fix
値を返却します
Promise.resolve()
.then(function(){
return 1;
})
.then(function(){
return 2;
})
;