非同期処理
同期処理とは
同期処理とは、「コードを上から順に1行ずつ実行し、前の処理が終わるまで次へ進まない」処理です。
const a = doSyncA();
const b = doSyncB(); // A が終わるまでここへは来ない
非同期処理とは
非同期処理とは、「ある処理を開始したら結果を待たずに次の行に進み、結果が返ってきたタイミングで後から登録しておいた処理(コールバックなど)を呼ぶ」仕組みです。例えば、重い処理(通信、ファイルI/Oなど)で“待ち”が発生しても、アプリ全体が止まらずほかの処理を動かし続けられます。
function doAsync() {
return new Promise(resolve => {
setTimeout(() => {
const resultA = /* 処理結果 */;
resolve(resultA);
}, 1000);
});
}
doAsync()
.then(a => {
console.log("A の結果:", a);
return doAsyncB(a);
})
.then(b => {
console.log("B の結果:", b);
})
.catch(err => {
console.error("エラー:", err);
});
Promise
Promiseとは
Promiseとは、非同期処理の結果を扱うオブジェクトです。
Promiseの基本構文:
const p = new Promise((resolve, reject) => {
// ここに非同期処理を書く
// 成功時:resolve(成功時の値)
// 失敗時:reject(エラーオブジェクト)
});
2つのコールバック関数
resolve()とreject()は、Promiseオブジェクトを作るときに使うコールバック関数で、非同期処理の「成功」か「失敗」を通知する役割を持ちます。
resolve(value):Promiseをfulfilled(成功)にして、value返す
reject(error):Promiseをrejected(失敗)にして、errorを返す
3つの状態
Promiseは以下の三つに状態が変化します。
fulfilled(成功):
非同期処理が正常に完了し、満たされた値(value)が手に入った状態。
resolve(value) が呼ばれると、pending → fulfilled に一度だけ移行します。
rejected(失敗):
非同期処理で何らかのエラーが起きた状態。
reject(error) が呼ばれると、pending → rejected に一度だけ移行します。
pending(保留):
Promise を生成した直後の初期状態。
非同期処理をまだ開始したばかり、あるいは結果が返ってきていない状態です。
*pending → fulfilled or rejected のどちらか一方にしか行けない
*fulfilled ⇄ rejected の間の遷移はない
結果の受け取り方
then/catch/finallyでPromiseの結果を受け取ります。
.then():
Promiseが「成功状態(fulfilled)」になった時に、resolve() に渡された値を受け取ります
.catch():
Promiseが「失敗状態(rejected)」になった時に、resolve() に渡された値を受け取ります
.finally():
必ず実行する最後の処理を記載します
p
.then(value => {
// resolve(value) 時に呼ばれる
console.log("成功:", value);
})
.catch(error => {
// reject(error) 時に呼ばれる
console.error("失敗:", error);
})
.finally(() => {
// 成否にかかわらず最後に必ず呼ばれる
console.log("処理完了");
});
具体例
1.setTimeout
function wait(ms) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`${ms} ミリ秒経過`);
}, ms);
});
}
wait(1000)
.then(msg => console.log(msg)) // → "1000 ミリ秒経過"
.finally(() => console.log("終わり"));
2.fetch
function fetchJson(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then(response => {
if (!response.ok) throw new Error("ステータス異常");
return response.json();
})
.then(data => resolve(data))
.catch(err => reject(err));
});
}
fetchJson("/api/data")
.then(json => console.log("取得データ:", json))
.catch(err => console.error("エラー:", err.message));
async
asyncとは
async関数は、「非同期処理を簡潔に書くための関数」のことです。関数定義の前に async を付けるだけで、その関数は常にPromiseを返す非同期関数になります。
// 関数宣言
async function foo() { … }
// 関数式
const bar = async () => { … }
return値を書くと、内部で Promise.resolve(値) が呼ばれたのと同じ結果になります。
throwエラーを書くと、内部で Promise.reject(エラー) が呼ばれたのと同じ結果になります。
何もreturnしなかった場合は、Promise(中身はundefined)が返ります。
async function ok() {
return "成功!";
}
async function ng() {
throw new Error("失敗!");
}
// Promise.resolve("成功!")相当のPromiseを返し、.then が呼ばれる
ok()
.then(v => console.log("ok then:", v))
.catch(e => console.log("ok catch:", e));
// Promise.reject(Error("失敗!"))相当のPromiseを返し、.catch が呼ばれる
ng()
.then(v => console.log("ng then:", v))
.catch(e => console.log("ng catch:", e.message));
await
awaitは、Promiseが完了する(成功または失敗する)まで「その行」の実行を一旦止めて待つ、非同期処理を同期処理のように書くためのものです。必ずasync関数の内部でだけ使えます。
asyncを付ける → 関数がPromiseを返し、awaitが使える
await → Promiseの完了(resolve/reject)を待ってから次の行に進む
(async () => {
const data = await fetch("/api/data").then(r => r.json());
console.log(data);
})();
具体例
1.setTimeout
function delay(ms: number) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function waitAndShowMessage() {
console.log("3秒待ってください...");
await delay(3000); // 3秒間待つ
console.log("お待たせしました!");
}
waitAndShowMessage();
2.fetch
async function fetchUser() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const user = await response.json(); // レスポンスをJSONとしてパース
console.log("ユーザー名:", user.name);
} catch (error) {
console.error("取得失敗:", error);
}
}