Onload có bằng readyState == 4 trong XMLHttpRequest không?


122

Tôi nhầm lẫn về sự kiện trả về xhr, như tôi có thể nói, không có quá nhiều khác biệt giữa onreadystatechange -> readyState == 4 và onload, có đúng không?

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

xhr.send(null);

hoặc là

xhr.onload = function() { /* do something */ }

13
Nếu ai đó đang xem đây là một ví dụ, hãy lưu ý rằng nó đang sử dụng async = false (đối số thứ 3 của xhr.open) - đây không phải là điều bạn muốn.
eddiewould

Câu trả lời:


65

Nó phải là một điều tương tự. onloadđã được thêm vào trong XMLHttpRequest 2 trong khi onreadystatechangeđã có từ thông số ban đầu.


Có vẻ như Safari di động không hoạt động trở lại khi sử dụng onload. onreadystatechange hoạt động, mặc dù.
Kai Hartmann

1
Không có sự phân tách rõ ràng thực sự giữa XHR 1 và XHR 2 nữa, chúng đã hợp nhất thành một tiêu chuẩn. Các tính năng phổ biến nhất mà đại diện XHR 2 là CORS hỗ trợ để từ đó quan điểm XHR 2 đã không xuất hiện trong IE cho đến khi IE 10 nhưng XHR.onload đã được hỗ trợ trong IE 9 mà vẫn thường được cho là XHR 1.
Chase

153

Điều này hầu như luôn đúng. Tuy nhiên, có một điểm khác biệt đáng kể là onreadystatechangetrình xử lý sự kiện cũng được kích hoạt readyState==4trong các trường hợponerror trình xử lý thường được kích hoạt (thường là sự cố kết nối mạng). Nó có trạng thái 0 trong trường hợp này. Tôi đã xác minh điều này xảy ra trên Chrome, Firefox và IE mới nhất.

Vì vậy, nếu bạn đang sử dụng onerrorvà đang nhắm mục tiêu các trình duyệt hiện đại, bạn không nên sử dụng onreadystatechangemà nên sử dụng onloadthay thế, có vẻ như được đảm bảo chỉ được gọi khi yêu cầu HTTP đã hoàn thành thành công (với phản hồi thực và mã trạng thái). Nếu không, bạn có thể nhận được hai trình xử lý sự kiện được kích hoạt trong trường hợp có lỗi (đó là cách tôi phát hiện ra theo kinh nghiệm về trường hợp đặc biệt này.)

Đây là liên kết đến chương trình thử nghiệm Plunker mà tôi đã viết cho phép bạn kiểm tra các URL khác nhau và xem chuỗi sự kiện và readyStategiá trị thực tế như ứng dụng JavaScript đã thấy trong các trường hợp khác nhau. Mã JS cũng được liệt kê bên dưới:

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();
}

2
@Fernando Để làm rõ, bên trong onload, readyState === 4đảm bảo là đúng sự thật?
kgf3JfUtW

6
@sam Có, điều đó dường như luôn luôn đúng, mặc dù điều ngược lại rõ ràng là không đúng, readyStatecó thể là 4 trên errorhoặc abortcác trường hợp khác. Trạng thái này về cơ bản có nghĩa là quá trình tải đã kết thúc, cho dù thành công hay không. Đối với tải bình thường, thành công, chuỗi sự kiện cuối cùng là: progress(với tất cả dữ liệu được tải), readystatechange(với readyState == 4) load,, loadend.
Fernando Echeverria

2
Hãy ghi nhớ rằng onloadcũng sẽ không kích hoạt nếuNo 'Access-Control-Allow-Origin' header is present on the requested resource.
deathangel908

Đúng. Đó là một trong những trường hợp kích hoạt trình onerrorxử lý.
Fernando Echeverria

1
@Pacerier: Có, vui lòng xem tại đây: plnkr test
Fernando Echeverria

10

Không, họ không giống nhau. Nếu bạn gặp lỗi mạng hoặc hủy bỏ hoạt động, onloadsẽ không được gọi. Trên thực tế, sự kiện gần nhất readyState === 4sẽ là loadend. Luồng trông như thế này:

     onreadystatechange
      readyState === 4
             
 onload / onerror / onabort
             
         onloadend
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.