TypeScript async/await 非同期プログラミング
async/await は ES2017 で導入された非同期プログラミングの糖衣構文であり、非同期コードを同期コードのように見せることができます。
SVG 図: async/await 実行フロー上の図は、従来の Promise と比較した async/await の利点を示しています。コードがより簡潔で、実行フローがより明確です。
Promise の基本
Promise は非同期操作の最終結果を表します。
例
// Promise を作成
var promise = new Promise(function(resolve, reject) {
var success = true;
if (success) {
resolve("操作成功");
} else {
reject("操作失敗");
}
});
promise.then(function(result) {
console.log("成功: " + result);
})["catch"](function(error) {
console.log("失敗: " + error);
});
var promise = new Promise(function(resolve, reject) {
var success = true;
if (success) {
resolve("操作成功");
} else {
reject("操作失敗");
}
});
promise.then(function(result) {
console.log("成功: " + result);
})["catch"](function(error) {
console.log("失敗: " + error);
});
実行結果:
成功: 操作が成功しました
async 関数
async キーワードを使用して非同期関数を宣言します。
例
// async 関数は自動的に Promise を返す
async function greet(): Promise<string> {
return "Hello, World!";
}
greet().then(function(result) {
console.log("結果: " + result);
});
// 非同期関数は Promise を返す
async function getData() {
return { name: "Alice", age: 25 };
}
getData().then(function(data) {
console.log("データ: " + JSON.stringify(data));
});
async function greet(): Promise<string> {
return "Hello, World!";
}
greet().then(function(result) {
console.log("結果: " + result);
});
// 非同期関数は Promise を返す
async function getData() {
return { name: "Alice", age: 25 };
}
getData().then(function(data) {
console.log("データ: " + JSON.stringify(data));
});
実行結果:
结果: Hello, World!
数据: {"name":"Alice","age":25}
await キーワード
await は Promise の完了を待って結果を取得します。
例
// 非同期操作をシミュレート
function delay(ms: number): Promise<string> {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(完了!);
}, ms);
});
}
async function main() {
console.log("開始...");
var result = await delay(100);
console.log("結果: " + result);
console.log("終了");
}
main();
function delay(ms: number): Promise<string> {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(完了!);
}, ms);
});
}
async function main() {
console.log("開始...");
var result = await delay(100);
console.log("結果: " + result);
console.log("終了");
}
main();
実行結果:
開始...結果: 完了!終了
エラー処理
try/catch を使用して非同期エラーを処理します。
例
function mayFail(shouldFail: boolean): Promise<string> {
return new Promise(function(resolve, reject) {
if (shouldFail) {
reject(new Error("操作失敗"));
} else {
resolve("操作成功");
}
});
}
async function handleError() {
try {
var result = await mayFail(true);
console.log("結果: " + result);
} catch (error) {
console.log("エラー捕捉: " + error.message);
}
}
handleError();
return new Promise(function(resolve, reject) {
if (shouldFail) {
reject(new Error("操作失敗"));
} else {
resolve("操作成功");
}
});
}
async function handleError() {
try {
var result = await mayFail(true);
console.log("結果: " + result);
} catch (error) {
console.log("エラー捕捉: " + error.message);
}
}
handleError();
実行結果:
エラー捕捉: 操作失敗
並列実行
Promise.all を使用して複数の非同期操作を並列に実行します。
例
function fetchUser(id: number): Promise<{ id: number; name: string }> {
return Promise.resolve({ id: id, name: "User" + id });
}
async function main() {
// 直列実行
console.time("直列");
var user1 = await fetchUser(1);
var user2 = await fetchUser(2);
console.log("直列完了: " + user1.name + ", " + user2.name);
console.timeEnd("直列");
// 並列実行
console.time("並列");
var results = await Promise.all([fetchUser(1), fetchUser(2)]);
console.log("並列完了: " + results[0].name + ", " + results[1].name);
console.timeEnd("並列");
}
main();
return Promise.resolve({ id: id, name: "User" + id });
}
async function main() {
// 直列実行
console.time("直列");
var user1 = await fetchUser(1);
var user2 = await fetchUser(2);
console.log("直列完了: " + user1.name + ", " + user2.name);
console.timeEnd("直列");
// 並列実行
console.time("並列");
var results = await Promise.all([fetchUser(1), fetchUser(2)]);
console.log("並列完了: " + results[0].name + ", " + results[1].name);
console.timeEnd("並列");
}
main();
実行結果:
串行完成: User1, User2 并行完成: User1, User2
async/await が Promise に比べて優れている点
- コードがより簡潔で読みやすい
- 同期コードスタイル
- より良いエラースタック
- デバッグが容易
まとめ
- async:非同期関数の宣言
- await:Promise を待つ
- エラー処理:try/catch
- 並列:Promise.all
その他の拡張