Chrome で XHR を abort() し続けるとそのうちリクエストが送信されなくなるのはどうにかならないのか
callback だけ無効にしてサーバサイドではちゃんとレスポンス返せってこと?
いまいち発生条件がつかめてないけど、ページロードしてからの累積回数で決まっているような気がしてならない。待ってても回復しない? というか abort() は自分でやってるんだから、余計なことしないでほしい。嫌なリクエストがくるならサーバ側ではじけばいいんだから……
以下のようなコードで再現する
上記の推測は間違っていて?、要は response body を待っている状態の XHR を abort() しても、Chrome はレスポンスを待ち続けるということらしい。HTTP ヘッダだけ先に送って body をストリームさせる場合にいろいろ困る。
#!/usr/bin/env corona
# vim:ft=perl:
use strict;
use warnings;
use Coro;
use Coro::Timer qw(sleep);
my $HTML = <<'EOF';
<!DOCTYPE html>
<html>
<title>test</title>
<h1>reproducing process</h1>
<ol>
<li>Request to remote server
<li>After requested, abort() it
<li>Try requesting another xhr (but this waits until aborted xhr response)
</ol>
<textarea cols="140" rows="20" id="log"></textarea>
<script>
document.getElementById('log').value = "";
function log (m) {
document.getElementById('log').value += m + "\n";
}
var seq = 1;
function req (time, callback) {
log('req:'+seq++);
var xhr = new XMLHttpRequest();
xhr.open('GET', '/api/test?' + time, true);
xhr.onreadystatechange = function () {
log([ xhr.readyState, xhr.responseText ]);
if (xhr.readyState == 4) callback();
};
xhr.send(null);
return xhr;
}
function req_abort (time, callback) {
var xhr = req(time, callback);
// setup timeout to send request to remote surely.
setTimeout(function () {
log('abort');
xhr.abort();
}, 100);
return req;
}
req(0, function () {
req_abort(10, function () {
req(1, function () { log('ok') }); // success after 10sec but should success after 1sec
});
}); // success;
</script>
EOF
sub {
my $env = shift;
warn $env->{REQUEST_URI};
my $sub = {
'/' => sub {
[ 200, [ 'Content-Type' => 'text/html' ], [ $HTML ] ];
},
'/api/test' => sub {
sub {
my $respond = shift;
my $writer = $respond->([ 200, [ 'Content-Type' => 'application/json' ] ]);
async {
sleep $env->{QUERY_STRING};
$writer->write('{ "ok": true }');
$writer->close;
};
};
},
}->{$env->{PATH_INFO}};
$sub ? $sub->() : [ 404, [ 'Content-Type' => 'text/plain' ], [ '404' ] ];
};