22
20

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 5 years have passed since last update.

そろそろ XHR を Fetch で置き換えれるようになってきた

Last updated at Posted at 2018-06-01

みなさんの記憶には、 Fetch ではリクエストのキャンセルや progress が取れなく、 XHR を置き換えることはできないといったイメージがあるかと思います。

ですが、ブラウザは常に進化しています。既にリクエストもキャンセルできますし、 progress も取得可能です(対応ブラウザに限る)。

以下で紹介します。

リクエストのキャンセル

fetch() メソッドには第2引数に signal を渡せます。この signal と AbortController を使うことでリクエストのキャンセルが実現できるのです。

const controller = new AbortController();
const signal = controller.signal;

setTimeout(() => controller.abort(), 10);

fetch('http://www.example.com/', {signal})
    .then(res => {
        return res.text();
    })
    .then(text => {
        console.log(text);
    })
    .catch(e => {
        if (e.name === 'AbortError') {
            console.error('The user aborted a request.');
        } else {
            console.error(e);
        }
    });

progress

これは XHR#onprogress を使っていた処理のことです。
Fetch では Streams API の ReadableStream を使って実現します。

fetch('<URL>')
    .then(res => {
        const total = parseInt(res.headers.get('content-length'), 10);
        let loaded = 0;

        return new Response(
            new ReadableStream({
                start(controller) {
                    const reader = res.body.getReader();

                    async function read() {
                        let result = await reader.read();
                        while (!result.done) {
                            const value = result.value;
                            loaded += value.byteLength;
                            console.log(`${loaded} / ${total}`);
                            controller.enqueue(value);
                            result = await reader.read();
                        }
                        controller.close();
                        return;
                    };
                    read();
                }
            })
        );
    })
    .then(res => res.blob())
    .then(data => console.log('download completed'))
    .catch(e => console.error(e));
progress.png
22
20
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
22
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?