はじめに
この記事は、社内勉強会の発表用として作成したものを、一部加工して公開しているものです。
間違っていることもあると思いますが、コメントで指摘していただけると幸いです。
Promiseのおさらい
- 非同期関数を扱うためのインターフェース
new Promise((resolve, reject) => {
//非同期処理
hoge.readFile(file, function(err, data){
if (err) {
reject(err); // errがあればrejectを呼び出す
return;
}
resolve(data); // errがなければ成功とみなしresolveを呼び出す
});
});
- resolveは成功時に呼ぶ関数
- rejectは失敗時に呼ぶ関数
Promiseってどういう風に使うの?
axios.get("https://hoge.fuga.com")
.then(response => console.log(response.status)) //成功時の処理
.catch(error => console.log(error.response.status)) //失敗時の処理
Promiseがつらいときってどんな時?
例えば…
非同期関数の結果を次の非同期関数で使いたいとき
then
のネストが増えていって辛い
asyncFunction1()
.then(value1 => {
return asyncFunction2(value1)
.then(value2 => {
return asyncFunction3(value1, value2)
.then(value3 => {
console.log(value3)
})
})
});
async,awaitとは
そういったPromiseの辛いところを簡潔に書ける(全てが全て書けるわけではない。)
また、雑に言うとasync,awaitはPromiseの処理のシンタックスシュガーなので、Promiseでできないことはできない。
asyncとは
非同期関数を定義する関数宣言のこと。
function や アロー関数に async を付けると「async 関数」を定義できます。
async 関数ってなにするの?
呼び出されるとPromiseを返す
⇒return
した場合その値がresolve
されたものとされる。
⇒throw
した場合その値がreject
されたものとされる。
あまり意味はないが、asyncだけ使用してawaitは使用しなくても大丈夫。
awaitとは
async関数
内でPromiseの結果(resolve、reject)が返されるまで待機する(処理を一時停止する)演算子のこと。
async function sample() {
//値が返ってくるまで待機
const result = await samplePromise();
console.log(result);
}
//Promiseで書くと…
function sample2(){
return samplePromise()
.then(result => {
console.log(result);
})
}
async,awaitの使用例
まずは簡単なものから
const hoge = () => Promise.resolve(1)
const fuga = () => Promise.resolve(2)
const main = () => {
hoge().then(x => {
fuga().then(y => {
console.log(x + y)
})
})
}
main()
↓
const hoge = async () => 1
const fuga = async () => 2
const main = async () => {
const x = await hoge()
const y = await fuga()
console.log(x + y)
}
main()
並列の非同期処理
Promise版
const hoge = value => {
return new Promise(resolve => {
setTimeout(() => {
resolve(value * 2);
}, 1000);
})
}
const fuga = value => {
return new Promise(resolve => {
setTimeout(() => {
resolve(value * 3);
}, 500);
})
}
const promiseAllSample = () => {
const promise1 = hoge(5);
const promise2 = hoge(10);
const promise3 = promise2.then(value => {
return fuga(value);
});
return Promise.all([promise1, promise2, promise3]);
}
promiseAllSample().then(([a, b, c]) => {
console.log(a, b, c); // => 10 20 60
});
async,await版
const hoge = value => {
return new Promise(resolve => {
setTimeout(() => {
resolve(value * 2);
}, 1000);
})
}
const fuga = value => {
return new Promise(resolve => {
setTimeout(() => {
resolve(value * 3);
}, 500);
})
}
const promiseAllSample = async () => {
const [a, b] = await Promise.all([hoge(5), hoge(10)]);
const c = await fuga(b);
return [a, b, c];
}
promiseAllSample().then(([a, b, c]) => {
console.log(a, b, c); // => 10 20 60
});
Array.map()
の利用も出来る。
const hoge = value => {
return new Promise(resolve => {
setTimeout(() => {
resolve(value * 2);
}, 1000);
})
}
const promiseMapsample = async () => {
const values =[5, 10, 15];
return await Promise.all(
values.map(async value => await hoge(value))
);
}
promiseMapsample().then(([a, b, c]) => {
console.log(a, b, c); // => 10 20 30
});
エラーハンドリング
async,awaitはPromiseのシンタックスシュガーなので、catch
をそのまま使える。
const errorHandling= async () => {
const result = await sample()
console.log(result) // エラー時は到達しない
}
errorHandling()
.catch(console.log)
おまけ
- axiosとかでよく使う書き方。いちいち
response.data
と書くのがめんどくさいときに
const { data } = await axios.get("https://hoge.fuga.com")
- awaitにしないほうが綺麗なとき。
const x1 = await func()
const x2 = await filter1(x1)
const x3 = await filter2(x2)
// ↓ ↓ ↓
const x = await func().then(filter1).then(filter2)
参考
Promise - JavaScript | MDN
Promiseを使う - JavaScript | MDN
async function - JavaScript | MDN
await - JavaScript | MDN
Promise と async/await の理解度をもう1段階上げる - Qiita
async/await 入門(JavaScript) - Qiita
async関数においてtry/catchではなくawait/catchパターンを活用する - Qiita