みなさんの記憶には、 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));