promise,async/awaitについて

2021/06/22に公開

現代の 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);//呼び出し
  1. fetchはpromise型を返す(resolve)
    👉 失敗したらcatch構文で取得できる(reject)
  2. 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を待機させることができる

GitHubで編集を提案

Discussion