同期処理と非同期処理
同期処理とはコードの順番通りに処理が実行されます。(基本プログラムは上から下に実行されます)
非同期処理はコードが書かれた順番通りに出力されないことです。
非同期処理で動かす
実際にコードで動かしてみました。
setTimeout(() => {}, 1000);//1000ミリ秒たった後にコールバック関数が実行
コールバック関数の中に出力します。
let A = 0;
setTimeout(() => {
A = 100;
}, 1000); //1000ミリ秒たった後にコールバック関数が実行
console.log(A);
//0
1000ミリ秒経つまで実行されないので0になっています。
Promise
JavaScriptは非同期言語なので、一つ前の実行に時間がかかったり、実行完了をまたずに次の処理が行われたりします。その時に使うのがPromise
です。
console.log("1番バッター");
setTimeout(() => {
console.log("2番バッター(1秒後に実行)");
}, 1000); //1000ミリ秒たった後にコールバック関数が実行
console.log("3番バッター");
//1番バッター
//3番バッター
このように2番バッターが出力されないような処理になってしまいますが、
Promiseを使うと、処理の順序に「約束」を付けることができます。
promiseの使い方
console.log("1番バッター");
// 約束を付けたい処理にPromiseを使う、インスタンス化
new Promise((resolve, reject) => {
//1秒後に実行する処理
setTimeout(() => {
console.log("2番バッター(1秒後に実行)");
//無事処理が終わったことを伝える
resolve();
}, 1000);
}).then(() => {
// 処理が無事終わったことを受けとって実行される処理
console.log("3番バッター");
});
//1番バッター
//2番バッター(1秒後に実行)
//3番バッター
Promiseのおかげで思った通りの処理ができました。
rejectも実行
rejectの実行法も見ていきます。基本不具合が発生した時に使います。
new Promise((resolve, reject) => {
//1秒後に実行する処理
setTimeout(() => {
console.log("2番バッター(1秒後に実行)");
//無事処理が終わったことを伝える
reject();
}, 1000);
})
.then(() => {
// 処理が無事終わったことを受けとって実行される処理
console.log("3番バッター");
})
.catch(() => {
console.log("catch実行");
});
//1番バッター
//2番バッター(1秒後に実行)
//catch実行
.catchを上のように使い、thenの処理は実行されず、catchの処理が実行されます。
もう少し簡単な処理もします。
const promise = new Promise((resolve, reject) => {
reject();
})
.then(() => {
console.log("resolveするぞ");
})
.catch(() => {
console.log("rejectした");
});
// rejectした
.thenが実行されずcatchが実行されました。
Promiseには3つの状態
Promiseには、PromiseStatusというstatusがあり、3つのstatusがある見たいです。
pending
: 未解決 (処理が終わるのを待っている状態)
resolved
: 解決済み (処理が終わり、無事成功した状態)
rejected
: 拒否 (処理が失敗に終わってしまった状態)
new Promise()
で作られたPromiseオブジェクトは、pendeing
という
PromiseStatus
で作られます。
処理が成功した時に、PromiseStatus
はresolved
に変わり,
then
に書かれた処理が実行されます。
処理が失敗した時は、
PromiseStatus
がrejected
に変わり、catch
に書かれた処理が実行されます。
上記文章も引用しました。
async/await
async
とawait
を使うとpromiseをもっと簡単に書けます。
async
は非同期関数を定義する関数宣言であり、関数の頭につけます。
awaitは、Promiseオブジェクトが値を返すのを待つ演算子で、
awaitは必ず、async function内で使います。
const lateTrain = (minitues) => {
new Promise((resolve) => {
setTimeout(() => {
resolve();
}, minitues);
}).then(() => {
console.log(`電車が${minitues}分遅れた`);
});
};
これを使ってPromiseの処理をasync/awaitで、リファクタリングします。
const lateTrain = async (minitues) => {
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, minitues);
});
// Promiseの結果が返ってくるまで実行されない
console.log(`電車が${minitues}分遅れた`);
};
最後にこの処理も実行します。
let A = 0;
init();
async function init() {
try {
const result = await new Promise((resolve, reject) => {
setTimeout(() => {
a = 1;
reject(A);
}, 1000);
});
console.log(result);
} catch (e) {
console.log("catchが実行", e);
}
}
//catchが実行 0
少し遅れて実行されます。
資料
小学生でもわかるasync/await/Promise入門【JavaScript講座】
【JavaScriptの基本】Ajax入門講座|非同期通信とAjaxとは