ushumpei’s blog

生活で気になったことを随時調べて書いていきます。

Promise + reduceで逐次処理

setIntervalでもいいですが、Promisereduceでもできるようです。

/* 逐次処理したいデータ */
const arr = [1,2,3,4,5];

arr.map( /* データの配列から`Promise`を返す関数の配列を作る */
  e => (
    () => new Promise(
      (res, _) => {
        setTimeout(
          () => {
            /* ここに処理を書く、ここではコンソールに出力 */
            console.log(e);
            res(e);
          },
          /* 処理の間隔 */
          1000
        );
      }
    )
  )
).reduce( /* reduceを使って、Promiseをthenでつなぐ */
  (p, c) => p.then(c),
  Promise.resolve() /* 初期値 */
)

一応のメリットは、処理を中断する際の記述がわかりやすくなることだと思います。

const arr = [1,2,3,4,5];

arr.map(
  e => (
    () => new Promise(
      (res, rej) => {
        setTimeout(
          () => {
            if(e == 4) return rej('4 is an unlucky number');
            console.log(e);
            res(e);
          },
          1000
        );
      }
    )
  )
).reduce(
  (p, c) => p.then(c),
  Promise.resolve()
).catch(
  e => console.error('Error!!!: ' + e)
)

ちゃんとする場合はsetTimeoutのコールバック関数内にtry...catchで記述するのがいいでしょう。

setTimeout(
  () => {
    try {
      if(e == 4) throw new Error('4 is an unlucky number');
      console.log(e);
      res(e);
    } catch(e) {
      rej(e);
    }
  },
  1000
);

感想

なんとなくメソッドチェーンにしたがる性分なのかもしれません。