Подтвердить что ты не робот

XMLHttpRequest всегда вызывает прослушиватель событий "load", даже если ответ имеет статус ошибки

Я использую FormData для ajax загрузки файла. Загрузка выполняется, но проблема в том, что обратный вызов "error" никогда не вызывается. Даже когда мой HTTP-ответ представляет собой внутреннюю ошибку сервера 500 (для проверки этого я настраиваю сервер на ответ 500), вызывается обратный вызов "load".

function upload_image() {
    var form = document.getElementById('upload_image_form');
    var formData = new FormData(form);

    var xhr = new XMLHttpRequest();
    xhr.addEventListener("load", function(e) {
        alert("Success callback");
    }, false);
    xhr.addEventListener("error", function(e) {
        alert("Error callback");
    }, false);
    xhr.open("POST", "/upload_image");
    xhr.send(formData);
}

Любые идеи? Я тестирую это в Chrome.

4b9b3361

Ответ 1

Эта настройка должна работать лучше для ваших нужд:

var req = new XMLHttpRequest();
req.open('POST', '/upload_image');
req.onreadystatechange = function (aEvt) {
  if (req.readyState == 4) {
     if(req.status == 200)
      alert(req.responseText);
     else
      alert("Error loading page\n");
  }
};
req.send(formData);

В вашем коде обратный вызов ошибок никогда не вызывается, поскольку он вызывается только ошибками сетевого уровня, он игнорирует коды возврата HTTP.

Ответ 2

Событие загрузки вызывается всякий раз, когда сервер отвечает сообщением. Семантика ответа не имеет значения; важно то, что сервер ответил (в данном случае с состоянием 500). Если вы хотите применить семантику ошибки к событию, вам необходимо обработать статус самостоятельно.

Ответ 3

function get(url) {
return new Promise(function(succeed, fail) {
  var req = new XMLHttpRequest();
  req.open("GET", url, true);
  req.addEventListener("load", function() {
    if (req.status < 400)
      succeed(req.responseText);
    else
      fail(new Error("Request failed: " + req.statusText));
  });
  req.addEventListener("error", function() {
    fail(new Error("Network error"));
  });
  req.send(null);
 });
}

код из EJS по примеру кода ясно, что ошибка сети не имеет ответа, она вызывает событие ошибки. Событие загрузки триггера ответа и вы должны решить, что делать с статусом ответа

Ответ 4

Расширяя ответ @rich remer, вот как вы можете получить доступ к статусу самостоятельно:

function upload_image() {
    var form = document.getElementById('upload_image_form');
    var formData = new FormData(form);

    var xhr = new XMLHttpRequest();
    xhr.addEventListener("load", function(e) {
        if(e.currentTarget.status < 400)
            alert("Load callback - success!");
        else
            alert("Load callback - error!");
    }, false);
    xhr.addEventListener("error", function(e) {
        alert("Error callback");
    }, false);
    xhr.open("POST", "/upload_image");
    xhr.send(formData);
}

Обратите внимание на доступ к свойству e.currentTarget.status события ответа (e). Похоже, что статус на самом деле доступен через любой из e.{currentTarget,target,srcElement}.status - e.{currentTarget,target,srcElement}.status я не уверен, какой из них следует использовать в качестве лучшей практики.