0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Fetch APIのResponseオブジェクトのjsonメソッドやtextメソッドはなぜPromiseを返すのか

Last updated at Posted at 2021-05-01

Fetch APIの使い方といえば

const response = await fetch("https://api.example.com/");
const json = await response.json();

のように、レスポンスオブジェクトを得るためにまずawait、そしてさらにそこからデータを取り出すためにもう一度Promiseの解決を待つ必要がある。これはなぜなのか。少し考えれば当たり前の話なのだが、日本語の記事が見つからなかったので書いておく。

ちなみにaxiosとかだと

import axios from "axios";
const json = await axios.get("https://api.example.com/");

これだけ。JSONのパースも暗黙的に行われるし、レスポンスヘッダがエラーだったらPromiseはリジェクトされる。うーんeasy。さすがVueの標準なだけのことはある。

今まであまり考えずに使ってきたが、よくよく考えれば当たり前だった。

fetchメソッドのMDNに詳しい説明が書いてある。

fetch()WindowOrWorkerGlobalScope ミックスインのメソッドで、ネットワークからリソースを取得するプロセスを開始し、レスポンスが利用できるようになったら満足するプロミスを返します。このプロミスはリクエストに対するレスポンスを表す Response で解決します。プロミスは HTTP エラーでは拒否されず、ネットワークエラーでのみ拒否されます。 HTTP エラーをチェックするには、 then ハンドラーを使用する必要があります。

簡潔で明確な説明である。Promiseがfullfilledになるのは、「レスポンスが利用できるようになったら」、つまりHTTPのレスポンスヘッダまで受信を終えてレスポンスボディの受信を開始するタイミングということなのだろう。

そして、fetchメソッドの戻り値に使用されているResponseオブジェクトは、Bodyを実装している。このオブジェクトはRequestオブジェクトにも実装されているが、その中核はbodyプロパティとしてアクセス可能な単なるReadableStreamだ。

image.png

ただ、Bodyにはリクエストボディやレスポンスボディを処理するための便利メソッドがたくさん用意されている。それがお馴染みのjsonやtextメソッドだ。ただ、JSONや文字列を返すためには、先にbodyのReadableStreamをメモリ上に最後まで読み切る必要がある。このため、これらのメソッドの戻り値はPromiseだったのだ。

Body.json()
Response ストリームを取得し、完全に読み込む。 ボディのテキストを JSON として解析した結果で解決する promise を返す。

Body.text()
Response ストリームを取得し、完全に読み込む。 USVString(テキスト)で解決する promise を返す。 レスポンスは常に UTF-8 でデコードする。

メモリの制限にかかるくらい大量のデータを扱う必要がある場合はBody#textやBody#arrayBufferよりもBody#bodyを直接使ったほうがよさそうだ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?