当サイトは、アフィリエイト広告を利用しています
javascriptの非同期処理でよく使うasync~awaitのawaitについて
正常に動作するときとしない時があるのでサンプルを書いて確認した。
結論をまとめると下記だった
それぞれ確認していく
async~awaitの基本的な使い方については下記でまとめている
wait関数の戻り値をPromise型にしなかった場合
asyncをつけていてもawaitは効かない
// async関数にするがPromise型で返さないconst wait = async (ms) => {setTimeout(() => (console.log("await")), ms);};// async関数const awaitFunc = async () => {console.log(1);await wait(3000); // Promise が返ってくるまで awaitで 処理停止させたいconsole.log(2); // 約3秒経過に表示};awaitFunc();// 実行結果// 1// 2// await
Promise型で返却した場合はawaitが効く
// setTimeout を Promise でラップconst wait = (ms) =>new Promise((resolve) =>setTimeout(() => resolve(console.log("await")), ms));// asyncconst awaitFunc = async () => {console.log(1);await wait(3000); // Promise が返ってくるまで awaitで 処理停止console.log(2); // 約3秒経過に表示};awaitFunc();// 実行結果// 1// await// 2
fetchAPIは結果がPromiseで帰ってくるため、明示的にnew Promiseする必要はない。
const fech = async () => {// awaitするconst result = await fetch("https://jsonplaceholder.typicode.com/todos/1", {method: "GET"}).then((response) => {if (response.ok) {// jsonに変換するreturn response.json();} else {// rejectthrow new Error(response.status);}})// rejectの結果を処理.catch((status) => console.log(status));console.log(result); //fetch処理が終了後に実行されるconsole.log("111");};fech();// 実行結果// {userId: 1, id: 1, title: "delectus aut autem", completed: false}// 111
awaitをけした場合はfetch処理のPromiseが解決される前にlog出力されるため
実行結果は下記のようになる
Promise {<pending>}111
axiosもfechAPIと同様に結果がPromiseで帰ってくるため、明示的にnew Promiseする必要はない。
import axios from "axios";const axiosSampleFunc = async () => {const result = await axios.request({method: "GET",url: "https://jsonplaceholder.typicode.com/todos/1",})// .then(res=>res.data).catch((error)=>error.message)console.log(JSON.stringify(result.data,null,2));console.log(1111);};axiosSampleFunc()// 実行結果// {// "userId": 1,// "id": 1,// "title": "delectus aut autem",// "completed": false// }// 1111
awaitを消した場合はaxios処理のPromiseが解決される前にlog出力されるため
実行結果は下記のようになる
undefined1111
XMLHttpRequestでawaitを使う場合は、結果がPromiseではかえって来ないため
new Promiseする必要がある
XMLHttpRequestを実行する関数の戻り値をPromiseにした場合
awaitが有効になる
// Promiseconst promiseFunc = async () => {// 戻り値をPromiseで取得するreturn new Promise((resolve, reject) => {// オブジェクト生成let xmlHttpRequest = new XMLHttpRequest();// responseTypeを設定(受け取る型)xmlHttpRequest.responseType = "json";// onloadイベントでリクエストの状況を監視xmlHttpRequest.onload = (e) => {if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status === 201) {resolve(xmlHttpRequest.response);} else {reject(xmlHttpRequest.status);}};// アクセス方法とパスを設定// アクセス方法// パス// true:非同期、false:同期xmlHttpRequest.open("POST","https://jsonplaceholder.typicode.com/todos",true);// サーバに対して解析方法を指定するxmlHttpRequest.setRequestHeader("Content-Type","application/json; charset=UTF-8");// 送るデータconst sendData = {userId: 1,id: 1,title: "delectus aut autem",completed: false};// 通信実行xmlHttpRequest.send(JSON.stringify(sendData));});};// 実行const asyncFunc = async () => {const result = await promiseFunc();console.log(result);console.log("aaa");};asyncFunc()// 実行結果// {userId: 1, id: 201, title: "delectus aut autem", completed: false}// aaa
Promiseで返さないとawaitが効かない
// Promiseconst promiseFunc = async () => {// 戻り値をPromiseで取得する// オブジェクト生成let xmlHttpRequest = new XMLHttpRequest();// responseTypeを設定(受け取る型)xmlHttpRequest.responseType = "json";// onloadイベントでリクエストの状況を監視xmlHttpRequest.onload = (e) => {if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status === 201) {return xmlHttpRequest.response;} else {return xmlHttpRequest.status;}};// アクセス方法とパスを設定// アクセス方法// パス// true:非同期、false:同期xmlHttpRequest.open("POST","https://jsonplaceholder.typicode.com/todos",true);// サーバに対して解析方法を指定するxmlHttpRequest.setRequestHeader("Content-Type","application/json; charset=UTF-8");// 送るデータconst sendData = {userId: 1,id: 1,title: "delectus aut autem",completed: false};// 通信実行xmlHttpRequest.send(JSON.stringify(sendData));};// 実行const asyncFunc = async () => {const result = await promiseFunc();console.log(result);console.log("aaa");};asyncFunc();// 実行結果// undefined// aaa
awaitを使う場合は、awaitしている関数内で使っている別の非同期処理も
awaitしていないawaitが効かなくなる。
awaitしているasync関数(waitRap)内で呼んでいる
async関数(wait)でもawaitしている場合は正常にawaitする
// setTimeout を Promise でラップconst wait = async(ms,count) =>new Promise((resolve) =>setTimeout(() => resolve(console.log(count)), ms));//waitをさらにラップしてさらにwaitを呼ぶconst waitRap = async(min,count)=>{// さらに非同期処理を呼ぶawait wait(min,count);}// asyncconst awaitFunc = async () => {console.log(1);await wait(3000,2); // Promise が返ってくるまで awaitで 処理停止console.log(3); // 約3秒経過に表示await waitRap(3000,4) //ラップ関数を実行console.log(5);};awaitFunc();console.log(6); //async関数外なので処理を待たない// 実行結果// 1// 6// 2// 3// 4// 5
waitRap内のawaitを消すと、awaitしなくなる
// setTimeout を Promise でラップconst wait = async(ms,count) =>new Promise((resolve) =>setTimeout(() => resolve(console.log(count)), ms));//waitをさらにラップしてさらにwaitを呼ぶconst waitRap = async(min,count)=>{// さらに非同期処理を呼ぶ// awaitを消すwait(min,count);}// asyncconst awaitFunc = async () => {console.log(1);await wait(3000,2); // Promise が返ってくるまで awaitで 処理停止console.log(3); // 約3秒経過に表示await waitRap(3000,4) //ラップ関数を実行console.log(5);};awaitFunc();console.log(6); //async関数外なので処理を待たない// 実行結果// 1// 6// 2// 3// 5// 4
async関数内でawaitをしてもasync関数外の処理はawaitされずに
実行される
// setTimeout を Promise でラップconst wait = (ms) =>new Promise((resolve) =>setTimeout(() => resolve(console.log("await")), ms));// asyncconst awaitFunc = async () => {console.log(1);await wait(3000); // Promise が返ってくるまで awaitで 処理停止console.log(2); // 約3秒経過に表示};awaitFunc();console.log(4); //async関数外なので処理を待たない// 実行結果// 1// 4// await// 2
console.log(4)はasync関数外のためPromiseの結果を待たず実行される