fetch API から XMLHttpRequest への置き換えを決意した話
最近 fetch API をヘビーに使うようになっていて、いろいろと勘所もわかってきていて、Promise
ベースなのはやっぱりすごく便利なんだけれども、現状だと機能が全然足りないなあ、と。
XMLHttpRequestUpload
相当がないのは知っていたし、困ったなあと思っていたんだけれども、XMLHttpRequestUpload
自体がだいぶレア目のヤツで使うような機会もまあめったにないので実害としてはそこまで大きくなかった。
んで、だ、XMLHttpRequestUpload
相当がないのは良いとしても、ReadableStream
で XMLHttpRequest
で言う progress
イベント相当のことをしようとしたときに、発火時にトータルの容量がわからんつう問題が発生した。
fetch API で ReadableStream
を使って progress
の状況を取るときは
function consume(reader) {
var total = 0;
return (function pump() {
return reader.read().then(function(args) {
if (!args.done) {
total += args.value.byteLength;
return pump();
}
});
})();
};
fetch('/path/to').then(function(response) {
var reader = response.body.getReader();
return consume(reader);
});
といったコードを使う。データを受信するごとに total
変数に、受信したデータのバイト数を追加していくことしかできない。
forbidden headers の中に Content-Length
があるからしゃあないちゃしゃあないような気もするんだけれども、どうしたもんかまじでわからん。
トータルの容量がわからんとなにが困るって、進捗の表示ができないんだよ。
xhr.onprogress = function(e) {
result.textContent = e.loaded / e.total;
};
ていうので XMLHttpRequest
だったら一瞬で進捗状況を表示させられていたけど、fetch API だとできない。いや仕様的には [[totalQueuedBytes]]
つうのがあるんだけれども internal slot 扱いで JavaScript から取ることはできない。
これ、誰も困っていないのかな。困るよなあ。困るよなあ。どうすんのまじでコレ。
っていうのと今日実装している最中であーってなったのは XMLHttpRequest.abort()
相当のものがないってこと。まじでどうすんだよこれ!!! 今週の土日で今書いているプロダクトで fetch API を使っている箇所を XMLHttpRequest
に置き換えるわ。やっぱり世界に fetch API は早かった。XMLHttpRequest
ですよ、やっぱり。
XMLHttpRequest
最高!!!
……
という話でおわるのも酷いので補足をしますが、ちゃんと要所を抑えて使うと fetch API は非常に便利です。
Promise
ベースというのはイベントベースの API よりもはるかに記述が単純で済みます。コードが煩雑になってしまうのを防ぎますし、この記事を書いている 2016 年 7 月時点では stage 3 の Async Functions (ES 2017 にはいるとうれしいですね) といっしょに使うことによって、コールバックファンクションばかりになってしまうということも避けられます。
今後も Promise
ベースの流れが続くのが幸いだと思いつつも、現状の fetch API は「つらいなあ」というお話です。そもそも fetch API は XMLHttpRequest
の代替というわけではないので、お門違いも甚しいんですけどね。
fetch API は Living Standard です。今後も改良が続けられていきます。この記事で上げている XMLHttpRequest
との差異もいづれ埋められて行くでしょう。わたしはこの記事が陳腐化してしまうことを切に祈っています。
世界がもっと平和になりますように。