Когда должен быть обработчик XMLHttpRequest onerror
У меня есть небольшая проблема с пониманием обработчиков XMLHttpRequest
. В спецификации указано об onerror
обработчике:
error
[Отправлено...] Когда запрос не выполнен.
load
[Отправлено...] Когда запрос успешно завершен.
Проблема в том, что это значит, что "запрос не сработал". Это может быть
- запрос не может быть выдан вообще (например, отказ в подключении и такие ошибки) или
- выше, плюс сервер вернул код ошибки (например, 404)
Кроме того, я хотел бы знать, означает ли это, что onerror
и onload
не должны запускаться одновременно.
Эта ссылка указывает, что обработчик onerror
должен выполняться в зависимости от кода status
и onload
в зависимости от readyState
. Это означает, что они не являются взаимоисключающими, однако я не думаю, что это авторитетная информация.
Я прошу, потому что, используя последний снимок Opera, я обнаружил, что onload
запускается даже по 404 статусу. Я знаю, что тестирование status
- это уверенная ставка, но я хотел бы знать, нужно ли мне что-то делать для каждой спецификации или просто обходной путь для ошибки в Opera.
Ответы
Ответ 1
Как указано в комментариях, onerror
срабатывает при сбое на сетевом уровне. Если ошибка существует только на уровне приложения, например, отправляется код ошибки HTTP, тогда срабатывает onload
. Вам нужно проверить код возвращаемого состояния явно в вашем обработчике onreadystatechange
.
Обратите внимание, что отклоненный междоменный запрос также запускает обработчик onerror
.
Ответ 2
В дополнение к ответу apsillers обратите внимание, что XMLHttpRequest обрабатывает перенаправления автоматически в фоновом режиме, поэтому вам не нужно проверять эти коды ответа в событии onload
(это событие будет вызываться только один раз - в финале вызов). Также обратите внимание, что в случае, если вы отправляете данные полезной нагрузки с помощью метода POST, и если запросы перенаправляются, XMLHttpRequest изменяет метод от POST
до GET
и отбрасывает любые данные полезной нагрузки по соображениям безопасности. Событие onload
все равно будет вызываться, но вам нужно будет повторно отправить запрос вручную снова в новый пункт назначения.