パイプラインPromise入門
突然ですが皆さんはこんなコードを書いていたりしませんか?
const result= fun3(func2(await func1()))
この書き方だとどの関数がどの引数をとっているか見ずらいですが、各関数の結果ごとに変数に代入したりするのも面倒くさいですよね!
そんな時にPromiseを使うとこのように書けます
const result = await func1().then(func2).then(func3)
これだと結構見やすくないですか?そう、見やすいんです。
このようにPromiseをパイプラインとして使うことでコードの可読性を上げることができます。
また、この方法を使うとエラーハンドリングも簡単になることがあります。
例えば以下のようなコードがあったとします。
try{
const result= fun3(func2(await func1()))
}catch(e){
console.error(e)
}
それを先ほどの手法で書き換えるとこうなります
const result = await func1().then(func2).then(func3).catch(console.error)
かなり見やすく、すっきりしたことがわかると思います
ここまでのテクニックは既に使っている方がいるかもしれません。
では、以下のパターンはどうでしょうか?
const result = func3(func2(func1()))
そう!このままでは起点となるfunc1
がPromiseを返さないので、パイプラインを始めることができません。
それでも意地でもパイプラインな書き方をしたいのであれば、以下のような書き方をすることができます。
const result = Promise.resolve(func1()).then(func2).then(func3)
こうすればPromiseパイプラインを使えますし、先ほどのエラーハンドリングもできます。
まだまだ行きます。さらに以下のパターンどうすればうまくパイプラインを使えるでしょうか
const result= fun4(func3(),func2(await func1()))
無茶苦茶見ずらいですがfunc4
が二つの引数をとっていることがわかります。
これをパイプライン化するとこうなります
const result = await func1()
.then(func2)
.then((value) => func4(func3(),value));
すこし改善されましたが、まだ見ずらいです。そこで、curry
という関数を作成します。
const curry =
<T, U, E>(func: (arg1: T, arg2: U) => E) =>
(a: T) =>
(b: U) =>
func(a, b);
そしてこのcurry
を使うと以下のように書けます。
const result = await func1().then(func2).then(curry(func4)(func3()));
すばらしい!!
そして最後に以下の場合をパイプライン化してみましょう。
const result = fun4(await func3(), func2(await func1()));
今のcurry
関数ではfunc3
が返したPromiseをうまく処理できません。
なので、curry
関数を以下のように書き換えます。
const curry2 =
<T, U, E>(func: (arg1: T, arg2: U) => E) =>
(a: T | Promise<T>) =>
(b: U | Promise<U>) =>
Promise.all([a, b]).then(([a, b]) => func(a, b));
そしてこれを使うと....
const result = await func1().then(func2).then(curry2(func4)(func3()));
😎😎 Perfect 😎😎
今回はここまでにしておきます。よきPromiseライフを!!
Discussion