Как отловить ошибку, выданную в методе onload XMLHttpRequest - PullRequest
0 голосов
/ 02 июня 2019

Я throw исключение из метода onload моего XMLHttpRequest объекта. Однако я не могу catch эту ошибку с помощью блока try catch.

У меня есть следующий код в моей _fetch(url, callback) функции:

const xhr = new XMLHttpRequest()

xhr.onload = function () {
  if (xhr.readyState === xhr.DONE) {
    // if (xhr.status === 200) callback(xhr.response)

    // throw a 'custom' error if the server responds with 501
    if (xhr.status === 501) throw new Error('Answer not found') /
  }
}

// rest of the fn

Затем я использую функцию _fetch:

try {
  _fetch(endPoint, response => console.log(response))
} catch (error) { // error not caught
  console.log(error)
}

Однако ошибка не обнаруживается, и вместо этого выдается ошибка - Uncaught Error: Answer not found

Что я пробовал:

  • try catching Метод send() объекта xhr в _fetch
  • try catching Метод open() объекта xhr в _fetch
  • с использованием метода onerror объекта xhr - не будет работать, потому что запрос успешно завершен

Итак, как я могу catch эту ошибку?

Чтобы попробовать полный код, посмотрите эту скрипку.


Зачем вам throw ошибка в методе onload?

Я получаю данные от определенного API, и из-за некоторых ограничений я не могу использовать fetch. Я использую XMLHttpRequest вместо этого. Сервер отвечает кодом ошибки 501 - Not Implemented, если отправленный запрос не может быть отвеченным . Таким образом, мне нужно выбрать этот код ошибки и выполнить некоторые функции.

Очевидно, есть и другие возможные способы достижения моей конечной цели, но мне трудно обернуться, почему это не сработает. Я прочитал как throw, так и XMLHttprequest, но у меня может быть неправильное понимание того, как работает один из них.

Ответы [ 2 ]

3 голосов
/ 02 июня 2019

Вы абсолютно можете использовать fetch, чтобы упростить это не только для себя, но и для работы с ошибками. Ссылка JSFiddle под этим кодом.

const url = `http://api.wolframalpha.com/v1/result?appid=H2R834-AUAJXG9KRV&i=%3F`
fetch(`https://cors-anywhere.herokuapp.com/${url}`)
.then(res => {
    console.log(res.status)
    if (res.status == 200) {
        return res.json()
    }
    else if (res.status == 501) {
        throw new Error("Answer not found")
    }
    else {
        throw new Error("Some other status code")
    }
})
.then(json => { 
    console.log(json) 
})
.catch(err => { 
    console.error(err)
})

https://jsfiddle.net/mparson8/ug1hoks8/9/

0 голосов
/ 02 июня 2019

Хотя вы можете использовать библиотеку, чтобы облегчить свою жизнь,

XMLHttpRequest onXXXX на самом деле являются обработчиками событий, а onload является лишь одним из многих возможных событий. Полный список здесь: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Events

В этом случае у вас отсутствует обработчик ошибок:

xhr.onerror( ... )

Кроме того, если у вас есть доступ к современному браузеру, используйте xhr.addEventListener('load'|'error'|..., ... ) вместо. Это фактически позволяет использовать несколько обработчиков, удалять обработчики и т. Д.


Относительно вашего образца кода:

function _fetch(url, callback)


const xhr = new XMLHttpRequest()

xhr.onload = function () {
  if (xhr.readyState === xhr.DONE) {
    // if (xhr.status === 200) callback(xhr.response)

    // throw a 'custom' error if the server responds with 501
    if (xhr.status === 501) throw new Error('Answer not found')
    // This can never be caught because async functions break the stack.
    // Intuition: If you can't return it, you can't throw either.
  }
}

// rest of the fn

Затем я использую функцию _fetch:

try {
  _fetch(endPoint, response => console.log(response))
} catch (error) { // error not caught
  console.log(error)
}

В этом случае вам нужно изменить обратный вызов выборки, чтобы использовать два параметра в стиле, аналогичном node.js

В частности: _fetch(endPoint, (err, resp) => ... )


xhr.onload = function () {
  if (xhr.readyState === xhr.DONE) {
    // if (xhr.status === 200) callback(null, xhr.response)

    // throw a 'custom' error if the server responds with 501
    if (xhr.status === 501) callback(new Error('Answer not found'), null);
  }
}

Конечно, разумно использовать обещания (или библиотеку). Убедитесь, что вы позвоните либо разрешите, либо отклоните хотя бы один раз.

function _fetch(endpoint, callback) {
   return new Promise( (resolve, reject) => {
      xhr.onload = function () {
        if (xhr.readyState === xhr.DONE) {
        // if (xhr.status === 200) resolve(xhr.response)

        // throw a 'custom' error if the server responds with 501
        if (xhr.status === 501) reject(new Error('Answer not found'));
        }
      }

   });
}

Это позволяет использовать его следующим образом:

_fetch(endpoint)
.then ( res => console.log('result', res) )
.catch( e => console.log('error', e);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...