promise,async/awaitについて
現代の JavaScript チュートリアルをもとに学習した
非同期についてわからなかったのでまとめる
その前に軽く関数の書き方を復習しておこう
関数の書き方について
関数宣言
function 関数名()
{
//処理
}
//呼び出し
関数名();
関数宣言は宣言より前に、関数呼び出しの記述を書くことができる
関数式
let 変数名 = function()//無名関数
{
//処理
}
//呼び出し
変数名();
関数式にするとFunctionオブジェクトの生成されるタイミングが、通常の変数定義と同じになり、関数式より前に関数を呼び出すことができない
アロー関数
let 変数名 = () =>
{
処理;
}
//let 変数名 = () => 処理;
//呼び出し
変数名();
アロー関数を関数式にしている形
非同期処理について
- 同期処理・・・上から順に処理を実行することで、ひとつの処理が終わるまで次の処理は行わない
-
非同期処理・・・コードを順番に処理していくが、ひとつの非同期処理が終わるのを待たずに次の処理を実行する
- 非同期処理では同時に実行している処理が複数ある
- JSはデフォルトで非同期処理
callback
- 呼び出したい関数の引数に別の関数を渡し、関数の中で別の関数の処理を発火させる方法
- 関数の引数に関数を渡せる、渡される関数のことをコールバック関数と呼ぶ
- 同期処理を実現する方法がよくとられていた
- 特に同期処理に直接関係しているわけではないが、callbackを使い、別の処理を関数でよんでいる
// コールバック関数を実行する関数
function hello(callback)
{
console.log('hello,');//通常ここで何らかのイベントを使って処理を止め(遅らせて)次のcallbackを発火させる 👉 同期処理の実現
callback();
}
let sampleCallback = function()
{
console.log('bye');
}
hello(sampleCallback);//sampleCallbackは関数
//出力結果:hello,bye
コールバック地獄
callback関数の中にcallback関数を入れることがふえ、ネストがどんどん深くなっていくこと
👉 リファクタしにくい
setTimeout(function(){
console.log('1秒');
setTimeout(function(){
console.log('2秒');
setTimeout(function(){
console.log('3秒');
},3000);
},2000);
},1000);
promise
オブジェクトの一種で、thenメソッドが使えるのが特徴
リファレンスでは「Promise オブジェクトは非同期処理の最終的な完了処理 (もしくは失敗) およびその結果の値を表現します」と書かれている
Promiseは三つの状態を持つ
- 値未確定
- 「待機(pending)」:保留中
- 値確定
- 「満足(fullfilled)」:処理が完了
- 「拒絶(rejected)」:処理のエラー
promiseの中の関数処理が確定するまではpromiseに「待機(pending)」を渡し、次の処理に行かせないことができる 👉 同期処理の実現
処理が終わるとpromiseにresolve(value)かreject(error)を返し、それぞれpromiseが
resolveなら「満足(fullfilled)」
rejectなら「拒絶(rejected)」
の状態となる
thenメソッド・・・promiseの値が確定した際に引数に書いた関数の処理を走らせ、同期処理を実現できる
promiseで実装した同期処理
const result = fetch('何かしらのurl');//
result.then(function(response)
{
console.log(response);
})
console.log(result);//呼び出し
- fetchはpromise型を返す(resolve)
👉 失敗したらcatch構文で取得できる(reject) - promise型はthenが使用でき、thenはpromiseの処理が確定した際に引数に書いた関数の処理を走らせるというもの
thenのメソッドチェーン
thenは処理を関数の外に切り出してるので、コールバック地獄のようにはならない
test = new Promise(function(resolve, reject) {
setTimeout(() => resolve(5), 3000);
})
test//変数
.then(function(result) {//呼び出す
console.log(result);//5
return result * 2;//10を返す
})
.then(function(result) {
console.log(result);//10
return result * 2;
})
.then(function(result) {
console.log(result);//20
});
async/await
promiseのシンタックスシュガー
asyncで定義された関数はpromiseを返すため下記のように.thenを使うことができる
シンタックスシュガー・・・同じ意味だけど楽にかける構文のこと 👉 ifと三項演算子など
async function f()
{
return '処理終了';
}
f().then(console.log); // 処理終了
awaitはasync関数の中でのみ動作する
async function f()
{
let test = new Promise((resolve, reject) => {
setTimeout(() => resolve('処理終了'), 5000)
});
let result = await test; // testの中のpromiseの値が確定するまでJavaScriptを待機させる、ここでは代入をストップ
console.log(result); // 処理終了
}
f();
まとめ
callback関数・・・関数の引数に別の関数処理をかける
promise・・・オブジェクトの一種、状態を3つもつ
then・・・promiseの値が確定した際に引数に書いた関数の処理を走らせる
async・・・返り値をpromiseにする関数定義
await・・・async関数内の何らかのpromiseの値が確定するまでJSを待機させることができる
Discussion