async / await とプロミスオブジェクト
プロミスオブジェクト
Section titled “プロミスオブジェクト”JavaScript で非同期的な処理を扱うために提供されている、 Promise API というものがあります。
Promise のインスタンスには、3つの状態があります。
pending: 処理待ち中。処理が終わると下の2つのいずれかに移行します。fulfilled: 処理が成功した状態。rejected: 処理が失敗した状態。
早速 Promise を作ってみましょう。
const promise = fetch("https://www.google.com");console.log(promise);$ bun run ./script1.tsPromise { <pending> }プロミスの基本メソッド
Section titled “プロミスの基本メソッド”Promise が fulfilled になった後に実行するコードを登録するために、then メソッドを使います。
const promise = fetch("https://www.google.com");
promise.then((resp) => { console.log(resp);});$ bun run ./script2.tsResponse (7.48 KB) { ok: true, url: "http://www.google.com/", status: 200, statusText: "OK", headers: Headers { /* 省略 */ }, redirected: false, bodyUsed: false,}Promise が rejected になった後に実行するコードを登録するために catch メソッドを使います。
const promise = fetch("https://not-exists.google.com");
promise.catch((err) => { console.log(err);});$ bun run ./script3.tserror: 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 オブジェクトを作ることもできます。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);$ bun run ./script4.ts1234async と await
Section titled “async と await”さて、お待ちかねの async / await です。
async キーワードを関数の宣言時につけることで、関数の内部で await というキーワードが使えるようになります。
await キーワードは、 Promise オブジェクトのような then メソッドをもつオブジェクトの非同期な扱いを、同期関数と同じような書き方で書けるようにする糖衣構文 (Syntax Sugar) です。
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 を返します。
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,// }, ...// ]