非同期のエラー処理
フロントでは非同期処理でエラーを捌くことが多い。
普通だったら Promise
で catch
すればいいが・・・
複雑なエラー処理
「複数の非同期 を 直列 で実行したい」
こういうとき、どうなるか
Promise でやる
これを見て欲しい。
function foo() {
return new Promise((resolve, reject) => {
let result_1;
fetch('/foo')
.catch(() => {
reject({ errorType: 1 });
return new Promise(() => {});
})
.then(_result_1 => {
result_1 = _result_1;
return fetch('/bar?result_1=' + result_1);
})
.catch(() => {
reject({ errorType: 2 });
return new Promise(() => {});
})
.then(result_2 => {
resolve({
messaga: 'fetch complete',
result_1,
result_2,
});
});
});
}
控え目に言ってナニコレ状態。
解説をつけたのがこちら。
function foo() {
return new Promise((resolve, reject) => {
let result_1;
fetch('/foo')
.catch(() => {
// fetch('/foo') のエラー処理
reject({ errorType: 1 });
// ここで処理止めたいが・・・
// 何もしないと次の then(1) へ進んでしまう
// throwすると次の catch(2) へ進んでしまう
// 苦肉の策、永遠にresolveしないPromiseを返して止める・・・
return new Promise(() => {});
})
.then(_result_1 => {
// result_1 を最後に返すためにわざわざlet
result_1 = _result_1;
// (1) 2つ目のfetch開始
return fetch('/bar?result_1=' + result_1);
})
.catch(() => {
// (2) fetch('/bar') のエラー処理
reject({ errorType: 2 });
// 苦肉の策、永遠にresolveしないPromiseを返して止める・・・
return new Promise(() => {});
})
.then(result_2 => {
resolve({
messaga: 'fetch complete',
result_1,
result_2,
});
});
});
}
つらい
async/await でやる
async/await
だと自然なコードにできて幸せ
async function foo() {
let result_1;
try {
result_1 = await fetch('/foo');
} catch (e) {
throw { errorType: 1 };
}
let result_2;
try {
result_2 = await fetch('/bar?result_1=' + result_1);
} catch (e) {
throw { errorType: 2 };
}
return {
messaga: 'fetch complete',
result_1,
result_2,
};
}
いい感じ。
しかし try/catch
のために let
を使わなきゃいけないし、インデントも増える。
try/catch
使ったら当たり前のごく普通のコードだけど。
try/catch
の見た目は慣れない。
Go みたいに書きたい
個人的に Go のエラーの書き方が好きなので、
Go みたいにエラー書けたらいいのになぁあああああ!!!
という願望がある。
イメージ
イメージではこんな感じに書きたい
// イメージです
async function foo() {
const result_1, err = await fetch('/foo');
if(err){
throw { errorType: 1 };
}
const result_2, err = await fetch('/bar?result_1=' + result_1);
if(err){
throw { errorType: 2 };
}
return {
messaga: 'fetch complete',
result_1,
result_2,
};
}
Go っぽく書いた
async function foo() {
const result_1 = await fetch('/foo').catch(e => e);
if (result_1 instanceof Error) {
throw { errorType: 1 };
}
const result_2 = await fetch('/bar?result_1=' + result_1).catch(e => e);
if (result_2 instanceof Error) {
throw { errorType: 2 };
}
return {
messaga: 'fetch complete',
result_1,
result_2,
};
}
イケるやん
個人で書くならこの書き方したい。
けど、少しトリッキーだから、
やっぱtry/catchで書くのがいいですかね。