awaitはPromiseという箱をかぶった非同期の箱を取り出して、
値を取り出して同期に戻すという役割があります。
なので最終的にPromiseなら何でも問題ありません。
純正のPromise流儀の書き方を続けて、
最後にawaitで待つような作りにしましょう。
Promise流儀の書き方は、
完了を.then
か.catch
のメソッドで待ち受けるという
一次元配列的な書き方が出来る事を目的としたやり方ですので、
下記のようなコードが成立します。
js
1var resp = await requestPromise.put(options)
2 .catch(() => requestPromise.put(options))
3 .catch(() => requestPromise.put(options))
4 .catch(() => requestPromise.put(options))
5 .catch(e => Promise.reject(new Error("データ更新に失敗しました。 ErrorMessage : " + e.message)));
上記のコードはPromiseの中にPromiseという風に
2重のPromiseの箱で包まれていますが問題ありません。
.then
や.catch
の戻り値でPromiseがネストしている場合、
それらを自動suna的に全て取り除いて値の状態にしてくれます。
なのでユーザーとしては気にせずPromiseを返すような処理を
がんがん.then
や.catch
メソッドでつないで行けば良いのです。
さて、上記のコードはベースです。
Promise作って.catch
メソッドをぶら下げるだけなので、
いろんな書き方に派生できますね。
同じ処理に着目して代入しながらfor文を使うことも可能です。
js
1var putReq = requestPromise.put(options);
2for (var i = 0; i < 3; i++) {
3 // 毎回代入させることで1度ずつ挑戦を実現できる
4 // 代入しない場合、最初の挑戦に失敗すると同時並行で3個のリクエスト処理が同時に飛んでしまう
5 putReq = putReq.catch(() => requestPromise.put(options));
6}
7putReq.catch(e => Promise.reject(new Error("データ更新に失敗しました。 ErrorMessage : " + e.message)));
8var resp = await putReq;
Lodaashなどのライブラリを使った関数型プログラミング的なアプローチならもう少し行数削れますね。
少々大道芸的ですが、reduce使ってワンライナーでやってみました。
js
1// まず1度も成功していない想定でPromise.rejectを作ってから.catchを4回ぶら下げる
2var resp = await [1, 2, 3, 4].reduce(
3 (p) => p.catch(() => requestPromise.put(options)),
4 Promise.reject()
5).catch(e =>
6 Promise.reject(new Error("データ更新に失敗しました。 ErrorMessage : " + e.message))
7);
【おまけ】 素直にasync/await構文で頑張る
async/await構文を使ってコードを書くとこんな感じになりますね。
Promiseの糖衣構文という制約上、catchを握りつぶすのでちょっとお行儀が悪いですね。
js
1var resp = null;
2for (let i = 0; i < 4; i++) {
3 try {
4 resp = await requestPromise.put(options);
5 break;
6 } catch (e) {} // お行儀が悪いがエラーは握りつぶす
7}
8if (resp == null) {
9 throw new Error("データ更新に失敗しました。 ErrorMessage : " + e.message)
10}
やはり.cache
メソッドをぶら下げながら、
ある程度の所まではPromiseで引っ張った方が綺麗に書けるでしょうね。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/11/09 16:58