PromiseとAsync/Awaitについて
Promiseとasync/awaitについて自分の中では理解しているけど、上手く説明できなかったので整理します。
一言で説明できるようになることを目的とします。
JavaScriptは処理を待てません!
console.log("1");
// 1秒後に実行する処理
setTimeout(() => {
console.log("2(1秒後に実行)");
}, 1000);
console.log("3");
1
3
2(1秒後に実行)
Callback
JavaScriptは処理を待てないので、、、
function loadScript(src) {
スクリプトを読み込む処理
}
loadScript("/myScript.js");
newFunction(); ← この関数はmyScript.jsを読み込みが終わるのを待ちません
このnewFunction()がmyScript.jsの内容を使用する場合にはnewFunction()は思うように動作しません。
そんな時にcallback関数という使い方があります
function loadScript (src, callback) {
スクリプトを読み込む処理
callback();
}
loadScript("/myScript.js", newFunction);
こうすることでスクリプトを読み込んだ後に、そのスクリプトの処理を使用する関数を呼ぶことができます。
しかし、ある非同期処理が終わった後にある非同期処理をやる、その処理が終わった後にまた次の非同期処理をやりたい、そしてまた次の、、、、、
といった場合にはネスト地獄が待っています。
loadScript("script1.js", function() {
loadScript("script2.js", function() {
loadScript("script3.js", function() {
.....
})
})
})
script1を読み込んだ 後に script2を読み込む その後に script3を読み込む、、、
このように微妙です。これを解決するためにPromiseがありmす。
Promise
Promiseとは
Promise:約束する
~ 処理を約束する
Promiseには3つの状態がある
・pending:未解決(処理が終わるのを待っている状態)
・resolved:解決済み(処理が終わり、無事成功した状態)
・rejected:拒否(処理が失敗に終ってしまった状態)
new Promise() で作られた Promiseオブジェクトは、pendeingというPromiseStatusで作られます。
処理が成功した時にPromiseStatusがresolvedになって、thenに書かれた処理が実行される。
処理が失敗した時にPromiseStatusがrejectedになって、catchに書かれた処理が実行される。
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});
promise.then(
result => alert(result), ← 1秒後に "done!" を表示
error => alert(error) ← 実行されない
);
let promise = new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
promise.then(
result => alert(result), ← 実行されない
error => alert(error) ← 1秒後に "Error: Whoops!" を表示
);
Promiseクラスの四つの静的なメソッド
- Promise.resolve(value) – 与えられた値で promise を解決(resolve)します
指定された値でresolveされたpromiseを返す。promiseでラップ
let promise = Promise.resolve(value);
- Promise.reject(error) – 与えられたエラーで promise を拒否(reject)します
error で拒否(reject)された promise を生成する。
let promise = Promise.reject(error);
- Promise.all(promises) – すべての promise が解決するのを待って、結果の配列を返します。 与えられた promise が拒否されると、それは Promise.all のエラーになり、他のすべての結果は無視されます。
並列に複数の promise を実行し、すべてが準備できるまで待つためのメソッド。
以下は3秒後に解決され、[1,2,3]を返す
Promise.all([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 3000)), // 1
new Promise((resolve, reject) => setTimeout(() => resolve(2), 2000)), // 2
new Promise((resolve, reject) => setTimeout(() => resolve(3), 1000)) // 3
]).then(alert);
- Promise.race(promises) – 最初の promise の解決を待ち、その結果/エラーが結果になります。
1番処理が早く完了する1が返ってくる
Promise.race([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(alert);
Async/Await
async/await は よりpromiseを快適に利用する特別な構文
Async関数
async を関数の前につけるだけで 関数は常にpromiseを返す。
自動的にpromiseでラップしてくれる
async function f() {
return 1;
}
// Promise<1>
f().then(alert); // 1
Await関数
awaitはasync関数内のみで動作し、promiseが確定するまでJavaScriptを待機させる。
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("done!"), 1000)
});
let result = await promise; // promise が解決するまで待つ
alert(result); // "done!"
}
f();
参考になった問題
非async から asyncを呼び出す時
async function wait() {
await new Promise(resolve => setTimeout(resolve, 1000));
return 10;
}
function f() {
// ...ここに何を書きますか?
// async wait() をして 10 を取得するのを待ちます
// 覚えておいてください、"await" は使えません
}
解
async function wait() {
await new Promise(resolve => setTimeout(resolve, 1000));
return 10;
}
function f() {
// 1秒後に 10を表示
wait().then(result => alert(result));
}
f();
ここで注意なのは、f()の後に処理がある場合はそれが先に実行されてしまうことがあること
上記の関数f()のあとに以下のような処理がある時
f();
alert("ほげ"); ← 先に実行される
参考