よく忘れるので(まぁググればけっこう出てくるのでメモの必要もそれほど感じなくなってきたけど)メモしておく。※よくよく見るとQiitaにも同じような記事結構ある。。。
Array要素を非同期な処理でPromiseを使って順次実行する場合、reduceを使うと便利という話。
下記のようなサンプルでいかがでしょうか。
var datas= [
{timeout:10, message:'Hello'},
{timeout:100, message:'Promise'},
{timeout:5000, message:'World'},
{timeout:100, message:'!!!'}
];
function sequentialExec(arr){
return arr.reduce(function(prev,current,index,array){
return prev.then(function(prevResult){
return new Promise(function(resolve,reject){
if(current && typeof current.timeout === 'number' && typeof current.message === 'string'){
setTimeout(function(){
console.log('Prev:%s, Current:%s',prevResult,current.message);
resolve(current.message);
},current.timeout);
}else{
reject(new Error('invalid data.'));
}
});
});
},Promise.resolve());
}
sequentialExec(datas).then(function(lastResult){
console.log('Process completed: %s', lastResult);
}).catch(function(e){
console.log('Process error: %s', e.message);
});
ということはこんな感じの作っておけば便利だったりするのかな?
Promise.reduce = function(arr,func){
return arr.reduce(function(prev,current){
return prev.then(function(result){
return new Promise(function(resolve, reject){
func(resolve,reject,result,current);
});
});
},Promise.resolve());
};
これを使うと、最初に書いたコードは
var datas= [
{timeout:10,message:'Hello'},
{timeout:100,message:'Promise'},
{timeout:5000,message:'World'},
{timeout:100, message:'!!!'}
];
function proc(resolve,reject,prevResult,current){
if(current && typeof current.timeout === 'number' && typeof current.message === 'string'){
setTimeout(function(){
console.log('Prev:%s,Current:%s',prevResult,current.message);
resolve(current.message);
},current.timeout);
}else{
reject(new Error('invalid data.'));
}
};
Promise.reduce(datas,proc).then(function(lastResult){
console.log('Process completed: %s', lastResult);
}).catch(function(e){
console.log('Process error: %s', e.message);
});
とかなるのかな。まぁ一応やりたいことに集中できるかなぁ。