概要
nodejs v4.2 LTS が出たので、generators の勉強を兼ねて mapSeries を async モジュールを使わず generators で自作してみたという話。
使用モジュール等
-
node
: v4.2.2 -
co
: v4.6.0
co.wrap
を利用することで思ったよりも簡単に出来ました。
while で作成した mapSeries
/**
* @param {Array} array
* @param {Function} iteratee
* @param {Object} thisArg
* @return {Promise}
*/
const co = require('co');
const mapSeries = co.wrap(function *(array, iteratee, thisArg){
const length = array.length;
const fn = thisArg ? iteratee.bind(thisArg) : iteratee;
let i = 0;
let result = Array(length);
while(i < length){
result[i] = yield Promise.resolve(fn(array[i]));
i++;
}
return result;
});
for-of で作成した mapSeries
こっちの方がすっきりしているように思えます。
/**
* @param {Array} array
* @param {Function} iteratee
* @param {Object} thisArg
* @return {Promise}
*/
const co = require('co');
const mapSeries = co.wrap(function *(array, iteratee, thisArg){
const fn = thisArg ? iteratee.bind(thisArg) : iteratee;
let result = [];
for(let item of array){
item = yield Promise.resolve(fn(item));
result.push(item);
}
return result;
});
実行結果
node-repl
> const arr = [ 123, 456, 789 ];
> const fn = (item) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('sync: ', item);
return resolve(item);
}, 1000 - item);
});
};
> mapSeries(arr, fn).then(console.log);
Promise { <pending> }
> sync: 123
sync: 456
sync: 789
[ 123, 456, 789 ]
並列で実行ならログは、 789 → 456 → 123 出るはず。順番に出てるのでうまく行っているっぽいです。
for-of の mapSeries でも同じ結果。
async モジュールを使う以外で、何か他に良い方法があったら教えてください。