Apakah onload sama dengan readyState == 4 di XMLHttpRequest?

122

Saya bingung tentang event pengembalian xhr, seperti yang saya tahu, tidak banyak perbedaan antara onreadystatechange -> readyState == 4 dan onload, apakah itu benar?

var xhr = new XMLHttpRequest();
xhr.open("Get", url, false);
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4)
    {
        /* do some thing*/
    }
};

xhr.send(null);

atau

xhr.onload = function() { /* do something */ }
Huang
sumber
13
Jika ada yang melihat ini sebagai contoh, perhatikan bahwa itu menggunakan async = false (argumen ke-3 dari xhr.open) - yang biasanya tidak Anda inginkan.
eddiewould

Jawaban:

65

Seharusnya sama saja. onloadtelah ditambahkan di XMLHttpRequest 2 sedangkan onreadystatechangetelah ada sejak spesifikasi aslinya.

JK
sumber
Sepertinya, Safari seluler tidak kembali saat menggunakan onload. onreadystatechange berfungsi.
Kai Hartmann
1
Tidak ada lagi pemisahan yang jelas antara XHR 1 dan XHR 2, keduanya telah digabungkan menjadi satu standar. Fitur paling umum yang mewakili XHR 2 adalah dukungan CORS sehingga dari sudut pandang tersebut XHR 2 tidak muncul di IE hingga IE 10 tetapi XHR.onload didukung di IE 9 yang biasanya diyakini sebagai XHR 1.
Chase
153

Ini hampir selalu benar. Satu perbedaan yang signifikan, bagaimanapun, adalah bahwa onreadystatechangepengendali kejadian juga dipicu readyState==4dalam kasus di mana onerrorpengendali biasanya dipicu (biasanya masalah konektivitas jaringan). Ini mendapat status 0 dalam kasus ini. Saya telah memverifikasi ini terjadi di Chrome, Firefox, dan IE terbaru.

Jadi, jika Anda menggunakan onerrordan menargetkan browser modern, Anda tidak boleh menggunakan onreadystatechangetetapi harus menggunakan onload, yang tampaknya dijamin hanya akan dipanggil ketika permintaan HTTP berhasil diselesaikan (dengan respons nyata dan kode status). Jika tidak, Anda mungkin akan mendapatkan dua event handler yang dipicu jika terjadi kesalahan (begitulah cara saya menemukan secara empiris tentang kasus khusus ini.)

Berikut ini tautan ke program uji Plunker yang saya tulis yang memungkinkan Anda menguji URL yang berbeda dan melihat urutan kejadian dan readyStatenilai yang sebenarnya seperti yang terlihat oleh aplikasi JavaScript dalam berbagai kasus. Kode JS juga tercantum di bawah ini:

var xhr;
function test(url) {
    xhr = new XMLHttpRequest();
    xhr.addEventListener("readystatechange", function() { log(xhr, "readystatechange") });
    xhr.addEventListener("loadstart", function(ev) { log(xhr, "loadstart", ev.loaded + " of " + ev.total) });
    xhr.addEventListener("progress", function(ev) { log(xhr, "progress", ev.loaded + " of " + ev.total) });
    xhr.addEventListener("abort", function() { log(xhr, "abort") });
    xhr.addEventListener("error", function() { log(xhr, "error") });
    xhr.addEventListener("load", function() { log(xhr, "load") });
    xhr.addEventListener("timeout", function(ev) { log(xhr, "timeout", ev.loaded + " of " + ev.total) });
    xhr.addEventListener("loadend", function(ev) { log(xhr, "loadend", ev.loaded + " of " + ev.total) });
    xhr.open("GET", url);
    xhr.send();
}

function clearLog() {
    document.getElementById('log').innerHTML = '';
}

function logText(msg) {
    document.getElementById('log').innerHTML += msg + "<br/>";
}

function log(xhr, evType, info) {
    var evInfo = evType;
    if (info)
        evInfo += " - " + info ;
    evInfo += " - readyState: " + xhr.readyState + ", status: " + xhr.status;
    logText(evInfo);
}

function selected(radio) {
    document.getElementById('url').value = radio.value;
}

function testUrl() {
    clearLog();
    var url = document.getElementById('url').value;
    if (!url)
        logText("Please select or type a URL");
    else {
        logText("++ Testing URL: " + url);
        test(url);
    }
}

function abort() {
    xhr.abort();
}
Fernando Echeverria
sumber
2
@Fernando Untuk klarifikasi, di dalam onload, readyState === 4dijamin benar kan?
kgf3JfUtW
6
@sam Ya, tampaknya selalu demikian, meskipun sebaliknya jelas tidak benar, seperti halnya readyState4 kasus erroratau abortkasus juga. Keadaan ini pada dasarnya berarti proses pemuatan telah selesai, apakah berhasil atau tidak. Untuk pemuatan normal dan berhasil, urutan kejadian terakhir adalah: progress(dengan semua data dimuat), readystatechange(dengan readyState == 4) load,, loadend.
Fernando Echeverria
2
Perlu diingat bahwa onloadjuga tidak akan memicu ifNo 'Access-Control-Allow-Origin' header is present on the requested resource.
deathangel908
Itu benar. Itulah salah satu kasus yang memicu onerrorpawang.
Fernando Echeverria
1
@Pacerier: Ya, silakan lihat di sini: tes plnkr
Fernando Echeverria
10

Tidak, mereka tidak sama. Jika Anda mengalami kesalahan jaringan atau membatalkan operasi, onloadtidak akan dipanggil. Sebenarnya, acara terdekat readyState === 4adalah loadend. Alurnya terlihat seperti ini:

     onreadystatechange
      readyState === 4
             
 onload / onerror / onabort
             
         onloadend
pengguna
sumber