Skip to content

async / await とプロミスオブジェクト

プロミスオブジェクト

JavaScript で非同期的な処理を扱うために提供されている、 Promise API というものがあります。

Promise のインスタンスには、3つの状態があります。

  • pending: 処理待ち中。処理が終わると下の2つのいずれかに移行します。
  • fulfilled: 処理が成功した状態。
  • rejected: 処理が失敗した状態。

早速 Promise を作ってみましょう。

script1.ts
const promise = fetch("https://www.google.com");
console.log(promise);
Terminal window
$ bun run ./script1.ts
Promise { <pending> }

プロミスの基本メソッド

Promise が fulfilled になった後に実行するコードを登録するために、then メソッドを使います。

script2.ts
const promise = fetch("https://www.google.com");
promise.then((resp) => {
console.log(resp);
});
Terminal window
$ bun run ./script2.ts
Response (7.48 KB) {
ok: true,
url: "http://www.google.com/",
status: 200,
statusText: "OK",
headers: Headers { /* 省略 */ },
redirected: false,
bodyUsed: false,
}

Promise が rejected になった後に実行するコードを登録するために catch メソッドを使います。

script3.ts
const promise = fetch("https://not-exists.google.com");
promise.catch((err) => {
console.log(err);
});
Terminal window
$ bun run ./script3.ts
error: Unable to connect. Is the computer able to access the url?
path: "https://not-exists.google.com/",
errno: 0,
code: "ConnectionRefused"
Promise のコンストラクター ここまでは、 Fetch API で作られた Promise オブジェクトに操作をしてきました。自分で Promise オブジェクトを作ることもできます。
script4.ts
const p1 = new Promise((resolve, _reject) => {
resolve(1);
});
p1.then(console.log);
const p2 = Promise.resolve(2);
p2.then(console.log);
const p3 = Promise.reject(3);
p3.catch(console.log);
const { promise: p4, resolve } = Promise.withResolvers();
p4.then(console.log);
resolve(4);
Terminal window
$ bun run ./script4.ts
1
2
3
4

asyncawait

さて、お待ちかねの async / await です。

async キーワードを関数の宣言時につけることで、関数の内部で await というキーワードが使えるようになります。

await キーワードは、 Promise オブジェクトのような then メソッドをもつオブジェクトの非同期な扱いを、同期関数と同じような書き方で書けるようにする糖衣構文 (Syntax Sugar) です。

script6.ts
async function main() {
try {
const res = await fetch("https://www.google.com");
console.log("got status", res.status);
const json = await res.json();
console.log("got json", json);
return "ok";
} catch (err) {
console.log("got error", err);
return "error";
}
}
main();

async をつけた関数はそれ自体が Promise を返します。

script6.ts
console.log(main());
// -> Promise { <pending> }
console.log(await main());
// -> "error"

await 自体にエラーハンドリングの仕組みは付属しないので、catch メソッドに代わるものとして try ~ catch を使います。

演習

https://jsonplaceholder.typicode.com/todos にアクセスすると、適当な Todo を返してくれます。

Fetch API を使って、ここで返される Todo を title で部分一致検索するような非同期関数を作ってみましょう。

解答例
async function getTodos(titleLike: string): Promise<Todo[]> {
const resp = await fetch("https://jsonplaceholder.typicode.com/todos");
const todos: Todo[] = await resp.json();
return todos.filter((todo) => todo.title.includes(titleLike));
}
console.log(await getTodos("fugiat"));
// [
// {
// userId: 1,
// id: 3,
// title: "fugiat veniam minus",
// completed: false,
// }, ...
// ]