LoginSignup
0
0

More than 5 years have passed since last update.

generator と promise を使って、mapSeries を自作

Posted at

概要

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 モジュールを使う以外で、何か他に良い方法があったら教えてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0