website

Javascript/Typescript Tech

【Javascript】シーケンサー(一連の処理の逐次実行)を実装する

2021年11月3日

「ロナえる」の夫です。

Javascriptの制御をやっていてい、一連の処理を逐次実行したい時があると思います。

A処理→B処理→C処理→D処理

といった形で、順番に処理をさせたい場合です。

今回は、この一連の(関数)処理の逐次実行をreducePromiseを利用して、実装します。

reduceとは?

reduceとは、配列要素の合算や累積処理に対して便利なメソッドです。

詳しくはこちらのreduceの説明を参照して下さい。

website
【Javascript】Array(配列)の使い方をまとめました

続きを見る

Promiseとは?

Promiseは非同期処理をしたい場合に利用します。

ある関数の戻り値としてPromiseを指定してあげて、その戻り値を受け取るまで、次の処理を待つということができます。

例えば、次のように使います。


const func1 = input => {
 console.log(input);
 return new Promise((resolve, reject) => resolve(input*5));
};

func1(2).then( val => {
 console.log(val*2);
});

// expected output
//-----------------
// 2
// 20

この例では、func1が実行され、その結果(Promise)を使ってthen以降の処理が実行されています。

では、このPromisereduceを逐次実行をしていきましょう。

reduceとPromise利用して一連の処理を逐次実行

やることは3つです。

  1. Promiseを利用して関数を定義する
  2. 関数を配列にまとめる
  3. reduceを使って逐次実行する

// 1.Promiseを利用して関数を定義する
// function 1
const func1 = val => {
  return new Promise((resolve, reject) => {
    resolve(val * 5)
  })
}

// function 2
const func2 = val => {
  return new Promise((resolve, reject) => {
    resolve(val * 2)
  })
}

// function 3
const func3 = val => {
  return new Promise((resolve, reject) => {
    resolve(val * 2)
  })
}

// 2.P関数を配列にまとめる
const promiseArr = [func1, func2, func3]

// 3.reduceを使って逐次実行する
function runPromiseInSequence(arr, input) {
  return arr.reduce(
    (promiseChain, currentFunction) => promiseChain.then(currentFunction),
    Promise.resolve(input)
  )
}
runPromiseInSequence(promiseArr, 10)
  .then(console.log)   // 200

Promiseとreduceを利用する理由

上の実装を見て、二つの疑問がある人もいると思います。

① Promiseを利用しなくても同じ結果では?

上の例だと確かにその通りです。

ただし、それは関数自体が処理を終わらせてから次に進む場合にのみ言えることです。

実際には、非同期な関数だと関数内部の処理が終わる前に次の処理へ進んでしまう場合があります。

そのため、Promiseで待ち合わせ処理をしないと、順々に処理を実行することができません。

② reduceを利用せずにawaitで待って次の処理を実行すればいいのでは?

この辺は好みの問題かもしれませんが、reduceを利用することでコードの見通しがよくなります。

ある一連の処理に対して、それぞれ配列を見れば大まかな処理がわかります。

また、配列自体を交換することで、シーケンスを動的に切り替えることも容易になります。

-Javascript/Typescript, Tech,
-, , ,