0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

javascript promise について

Last updated at Posted at 2020-12-17

始めに

javascript学習中であり、学習様にまとめます。非同期処理の仕組みを振り返り、promise、async awatを学習していきます。

同期処理 非同期処置

  • 同期処理

  • メインスレッドでコードが順々に実行される。

  • 1つの処理が終了しないと、次の処理へ移行しない。

  • 本来処理はコールスタックに積まれていきその積まれたスタック(実行中のコードのコンテキスト)がlast in first outの原則で処理がスタックがはけていく。

  • 非同期処理

  • 同期処理は処理が実行されるまで次の処理が移行しないが、非同期処理を行うことで、処理をメインスレッドから分離ができる。

  • この分離している期間を利用して、次の同期的処理を実行できると言うことだ。

  • 分離された処理が全てのコールスタックがはけて、戻ってこれる。

同期
スクリーンショット 2020-12-16 23.11.15.png
非同期
スクリーンショット 2020-12-16 23.11.28.png

タスクキュー

  • 実行待ちの非同期処理の行列
  • 非同期処理の実行順はfirst in first outの原則からキューの中に入ってきた処理順に実行される

非同期処理の例

setTimeoutは一般的な非同期処理である
ここでのconsole.logの実行中を見ると、test()を実行した段階で、setTimeoutによって処理の分離が行われる。そしてtest2が実行。そして、次のコンテキストに移り、test3が実行。
test3が実行された段階で、キューからコールスタックに切り離された処理が戻り、task3が実行される。


//非同期処理の例
const test = () => {
  setTimeout(() => {
    console.log("test1");
  }, 4000);

  console.log('test2');
};

const test2 = () => {
  console.log('test3');
}

test();
test2();

//console.logの表示順
test2->test3->test

非同期処理のチェーン

非同期処理はチェーンできるが、繋げれば繋げるほど可読性が悪くなる

const test = (callback, val) => {
  setTimeout(() => {
    console.log(val++);
    callback(val);
  }, 1000);
};

test((val) => {
  test( (val) => {}, val)
}, 1);

その為作られたのがpromise

Promise

  • 非同期処理を簡単に書ける様にした仕組み
  • 非同期処理を操作できるオブジェクト。
  • promiseの引数として、resoleve, rejectをとることができる。
  • promiseは.thenメソッドでチェーンとして処理をつなげることができる
  • サーバーに繋ぐ .then データを取得します .then データを取得したら処理をします。と言う具合に処理を繋げることができる。
  • 状態とはresolve(ok)、reject(ng)として受け取ることができる。

構文としては


//Promiseはコールバックをとる。その引数にresolve、rejectをとることができる。
const test = new Promise((resolve, reject) => {
  //同期処理
}).then(() => {
  //非同期処理(resolveを待つ)
}).catch( () => {
  //非同期処理(rejectを待つ)
}).finally( () => {
  //非同期処理
})


then()メソッドの記述


const test = new Promise((resolve, reject) => {
  //引数で受け取ったresolveを使用する。
  resolve("hello");
}).then((data) => {
//resoleve()の引数がthen()の引数となる。
  console.log(data);
});

//catchの場合

const test = new Promise((resolve, reject) => {
  reject("test");
})
  .then((data) => {
    console.log(data);
  })
  .catch((data) => {
    console.log(data)
    //次then()にdataを渡す場合
    return data;
  }).then( (data) => {
     console.log(data);
  });

console.log("globle test");
結果: globle test, test

//rejectはPromiseで渡すコールバックでしか使用できないので、then()なで処理の分岐をする場合はthrow new Errorで処理の分岐を行う

const test = new Promise((resolve, reject) => {
  reject("test");
})
  .then((data) => {
    console.log(data);
    throw new Error()
  })
  .catch(() => {
    console.log("error catch");
  });

console.log("globle test");
結果globle test , error catch

Promiseチェーン

promiseを使用して複数の非同期処理を実行する。


const testPromise = (val) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(val++);
      resolve(val);
    }, 4000);
  });
};

//testPromiseを実行してタイミングで戻り値としてpromise関数が返却されるのでthen()が使用できる
testPromise(0)
   //ここの引数のvalはtestPromise関数の引数であるval
   //なぜvalの値が0にならにかと言うと、処理を連続して繋げているから
  .then((val) => {
    return testPromise(val);
  })
  .then((val) => {
   //return で必ずPromiseのインスタンスを返さないと処理が切れてしまう。
    return testPromise(val);
  });

Aysnc Await

Pomiseをさらに直感的に書ける様にした仕組み

Async

  • promiseを返却する関数を宣言する。関数の前にaysncをつける

Await

  • promiseを返却する関数の非同期処理が実行されるまで待つ。
  • 処理が実行されたら次の処理に移る

実際のコード


const testPromise = (val) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(val++);
      resolve(val);
    }, 4000);
  });
};

//asyncで宣言を行う
const test = async () => {
 //awaitで非同期処理が完了するまでまつ。その結果を変数に代入する
  let val = await testPromise(0);
  console.log(val);
};

test();

//処理を繋げることも可能

const test = async () => {
  let val = await testPromise(0);
  val = await testPromise(val);
  val = await testPromise(val);
  val = await testPromise(val);
  val = await testPromise(val);
};

test();

Promiseを使用しているのでもちろんthen()を使用できる.


const testPromise = (val) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(val++);
      resolve(val);
    }, 4000);
  });
};

const test = async () => {
  let val = await testPromise(0);
  val = await testPromise(val);
  return val;
};

//test()でもpromiseの処理の後にthen()が実行される
test().then(() => {
  console.log("hello" + val);
});

error catchもできる


const testPromise = (val) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(val++);
      resolve(val);
    }, 4000);
  });
};

const test = async () => {
  let val = await testPromise(0);
  val = await testPromise(val);
  throw new Error();
  return val;
};

test()
  .then((val) => {
    console.log("hello" + val);
  })
  .catch((e) => {
    console.log(e);
  });

try catch

promiseチェーンで処理を繋げて,exceptionがあれば.catchでエラーを出力していたが、try , catch文でも同様のことができる。

import React, {useState, useEffect} from 'react'
import axios from 'axios';

const User = () => {
    const [user, setUser] = useState({});
  
    const getUser = async () => {
      try {
           const res = await axios.get('api_path');
           setUser(resd.data);
      } catch(err) {
           console.log(err);
      }
   }
   
   useEffect(() => {
       getUser();
   }, [])
}

終わりに

非同期処理を学習しました。次ぎはtry catchを追加していこうと思います。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?