Promiseとasync&awaitの実践的な記述を比較
非同期処理を行う関数の記述例
非同期処理を同期(逐次)処理っぽくす関数記述の事例です。
同期処理っぽくとは、関数内の非同期な処理が終わるまでreturnしない関数という意味です。
これをPromiseとasync&awaitで下記比べてみました。
どちらの書き方が解りやすいかは慣れと用途次第です。
Promiseで書いた方は
・非同期だよという事がはっきりしている
・resolve,rejecをcallbackなアロー関数内でもOKなので便利
async&awaitで書いた方は
・一見簡単そう
・でも例外処理の考慮の記述したい場合はわかしずらい
・Promise化されていないsetTimeoutの様なcalback処理を含む場合はPromiseでラッピングする煩わしさがある
ということでPromise記述は例外処理も考慮するこだわり派に向いている。ただしPromiseという概念の理解が必要。
async&awaitは例外処理等を考慮する必要がなければ平易なコードで書ける。だが、拘り始めると途端に煩雑なコードになる。
まるでXMLHttpRequestとfetchの違いみたいなもの。
なお事例の呼び出し側はThenとcatchとfinallyで非同期っぽく書きました。
慣れると処理の流れを組み立てやすい。
Promiseの事例
3秒後にリターンする非同期関数の事例
function sample(arg) {
return new Promise((resolve, reject) => {
if (arg == "ok") {
setTimeout(() => {
resolve(`It's OK`);
}, 3000);
} else {
setTimeout(() => {
reject(`It's NG`);
}, 3000);
}
});
}
sample("ok")
.then((value) => {
console.log(`resolve return:${value}`); //3秒後に戻りはresolveで"OK"が表示される
})
.catch((err) => {
console.log(`reject return:${err}`);
})
.finally(() => { //finallyで逐次処理としてつなげる
sample("ng")
.then((value) => {
console.log(`resolve return:${value}`);
})
.catch((err) => {
console.log(`reject return:${err}`); //3秒後に戻りはrejectで"NG"が表示される
});
});
asyncとawaitの事例
3秒後にリターンする非同期関数の事例
*1 setTimeoutをawaitさせてい場合
Promise化されていないcallback関数をawaitさせる場合は、Promiseでラッピングする。
async function sample(arg) {
if (arg == "ok") {
await new Promise(resolve => setTimeout(resolve, 3000)); // 3秒待つ(*1)
return(`It's OK`);
} else {
await new Promise(resolve => setTimeout(resolve, 3000)); // 3秒待つ(*1)
throw new Error(`It's NG`); //Promiseのrejectの様な動作になる
}
}
sample("ok")
.then((value) => {
console.log(`OK return:${value}`); //3秒後に戻りはresolveで"OK"が表示される
})
.catch((err) => {
console.log(`NG return:${err}`);
})
.finally(() => { //finallyで逐次処理としてつなげる
sample("ng")
.then((value) => {
console.log(`OK return:${value}`);
})
.catch((err) => {
console.log(`NG return:${err}`); //3秒後に戻りはrejectで"NG"が表示される
});
});
その他、実践的な事例は気が向いたら追記します。
実践的な記述方法で、もっとスマートにロジックを組み立てる方法があったら教えて下さい。