如何捕获XMLHttpRequest的onload方法中引发的错误

时间:2019-06-02 13:56:16

标签: javascript ajax xmlhttprequest

我正在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出现该错误?

要尝试完整的代码,请查看this小提琴。


为什么需要在throw方法中onload出错?

我正在从某个API获取数据,由于某些限制,我无法使用fetch。我改用XMLHttpRequest。如果无法回答,服务器将以错误代码501 - Not Implemented进行响应。 因此,我需要挑选出该错误代码,并执行一些功能。

很明显,还有其他可能的方法可以实现我的最终目标,但是我发现很难为为什么这行不通。我已经阅读了throwXMLHttprequest,但可能对其中之一的工作方式有误解。

2 个答案:

答案 0 :(得分:3)

您绝对可以使用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/

答案 1 :(得分:-1)

虽然您可以使用图书馆来简化生活,

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

在这种情况下,您需要修改提取的回调以在similar style to 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);
  }
}

当然,聪明的方法是使用Promise(或库)。确保至少调用一次“解决”或“拒绝”。

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