156
133

More than 3 years have passed since last update.

【メモ】XMLHttpRequestのイベントについて

Last updated at Posted at 2016-05-02

(2021/08/29 追記)

既に fetch を使っても問題なくなっているので XMLHttpRequest の代わりにそちらを利用することをおすすめします。


この記事について

XMLHttpRequest(以下、XHR)のイベントの仕様って、そういえばきちんと把握してないなと思ったので少し調べてみました
その結果をつらつらと書いていきます

通信の終了/成功or失敗の調べ方

本題のイベントに入る前におさらいです
後々必要になります

readyState

xhr.readyStateは以下のいずれかの値を持ちます

定数 状態
0 UNSENT XHRオブジェクトの作成直後
1 OPENED open()メソッドの呼び出し後
2 HEADERS_RECEIVED レスポンスヘッダの受信後
3 LOADING レスポンスボディを受信中(繰り返し実行される)
4 DONE XHR通信の完了後

readyStateが4なら通信終了です

status

レスポンスのHTTPステータスです
readyStateが2以上の時アクセス可能で、4になった時に最終的な値が確定します
0なら通信に失敗、0以外なら通信に成功したことを表します
ただし、statusが0以外であってもサーバーへのリクエストが成功したとは限りません(404, 500など)

XHRのイベント

XHRが通信中に起こすイベントは以下の8個

  • onreadystatechange
  • onloadstart
  • onprogress
  • onloadend
  • onload
  • onerror
  • onabort
  • ontimeout

onreadystatechange

もっとも古くから存在する(?)イベントです
readyStateの値が更新されるたびに呼び出されます

onloadstart

open()メソッドが呼ばれたタイミングで呼び出されます
つまり、下の二つは同じです

xhr.onloadstart = function() {
  // do something
}
xhr.onreadystatechange = function() {
  if(xhr.readyState === 1) {
    // do something
  }
}

onprogress

レスポンスボディの受信中に繰り返し呼び出されます
つまり、下の二つは同じです

xhr.progress = function() {
  // do something
}
xhr.onreadystatechange = function() {
  if(xhr.readyState === 3) {
    // do something
  }
}

onloadend

受信が終了した時に呼び出されます
onloadendは受信の成功or失敗に関わらず呼び出されるので、後述するonloadonerrorを合わせたものだとも言えます
つまり、以下の3つは同じです

xhr.onloadend = function() {
  // do something
}
xhr.onload = function() {
  // do something
}
xhr.onerror = function() {
  // do something
}
xhr.onreadystatechange = function() {
  if(xhr.readyState === 4) {
    // do something
  }
}

onload

受信が成功した時に呼び出されます
つまり、以下の2つは同じです

xhr.onload = function() {
  // do something
}
xhr.onreadystatechange = function() {
  if(xhr.readyState === 4 && xhr.status !== 0) {
    // do something
  }
}

onerror

受信が失敗した時に呼び出されます
つまり、以下の2つは同じです

xhr.onerror = function() {
  // do something
}
xhr.onreadystatechange = function() {
  if(xhr.readyState === 4 && xhr.status === 0) {
    // do something
  }
}

onabort

通信がabort()メソッドによって中断された場合に呼び出されます
これはonreadystatechangeでは代用できません

ontimeout

接続がタイムアウトした場合に呼び出されます
一応、setTimeoutやらを使えばreadystatechangeで代用は可能ですが割愛します

その他

以下の4つのイベントは同時に発火することがありません

  • onload
  • onerror
  • onabort
  • ontimeout

よって、4つ全て指定しないと通信の終了を取りこぼす可能性があります
ちなみに、それぞれのイベントでのreadyStatestatusは以下のようになります

イベント readyState status
onload 4 0以外(レスポンスによる)
onerror 4 0
onabort 通信の進行度による 0
ontimeout 通信の進行度による 0

そもそも、onerrorってどんなときに発火するのかについてですが、例えばXHRのCross-Origin制約に引っかかった場合やネットワーク接続ができない場合など、サーバーとの接続ができなかった場合にerrorとなるようです

まとめ

通信の終了を検知したい場合は, 上記の4つのイベントを見ていれば大丈夫なようです
プログレスバーを実装したい場合は、onprogressを使ってイベントオブジェクトから総バイト数と受信済みバイト数が取得可能なようなので、それで事足りそうです

156
133
1

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
156
133