Why do fetch errors not have a stacktrace in my single page application?

久未见 提交于 2020-06-29 13:26:33

问题


I have two simple wrappers that handle requests in my single page application. One wraps fetch and throws an error if a response is not ok (not in the 200-300 range):

const fetchy = (...args) =>
  fetch(...args).then(response => {
    if (response.ok) {
      return response
    }

    throw new Error(response.statusText)
  })

export default fetchy

And one wraps fetchy and is used for GET requests:

const get = endpoint => {
  const headers = new Headers({ Authorization: `Bearer ${TOKEN}` })
  const init = { method: 'GET', headers }

  return fetchy(endpoint, init)
}

Now I'm using them in an action like so (this is a redux-thunk action creator) :

export const fetchArticles = () => dispatch => {
  dispatch({ type: types.FETCH_ARTICLES })

  return get(endpoints.ARTICLES)
    .then(response => response.json())
    .then(data => normalize(data.items, [schemas.articles]))
    .then(normalized => dispatch(fetchArticlesSuccess(normalized)))
    // fetch errors caught here do not have error.stack
    .catch(error => dispatch(fetchArticlesFail(error)))
}

So I'm catching both errors in fetch itself (network errors), and errors returned from the fetchy wrapper (api errors). The problem is that network errors from fetch, caught in fetchArticles, do not contain a stack trace. So error.stack does not exist. Which is messing up my error reporting.

It is a valid error, and error instanceof Error === true and error.message === 'Failed to fetch'. So why does this error not have a stack trace? How can I fix it? It seems like maybe I could add an error callback to fetchy and re-throw any errors there, but that seems weird to me (but maybe I'm wrong).


回答1:


The fetch error is created asynchronously & not directly related to a particular line of JavaScript. Although I agree it would be helpful if the line of the fetch call was included. I've filed a bug for this https://bugs.chromium.org/p/chromium/issues/detail?id=718760

As a workaround, you could catch the fetch error, and throw a new error if there are no numbers in the stack:

function fetchy(...args) {
  return fetch(...args).catch(err => {
    if (!err.stack.match(/\d/)) throw TypeError(err.message);
    throw err;
  }).then(response => {
    if (response.ok) return response;
    throw Error(response.statusText);
  });
}

Here's an example of that running http://jsbin.com/qijabi/edit?js,console




回答2:




Recently I faced the same error. Production channel logged this error for about 500 times in just 2 months and it really got irritating. Ours’ is a rails application with frontend powered by react.

Here is what was happening in our case. When the page loads, the refresh button changes to cross button, now if some api request is in progress during this page loading time and the user click this cross button, then chrome browser throws this error. For the same situation Firefox throws NetworkError when attempting to fetch resource.This is not really an issue which we should be worried about, and so we decided to make sentry ignore this error by using the ignoreErrors attribute of sentry.

Sentry.init({
  dsn: "sentry_dsn",
  ignoreErrors: [
    'TypeError: Failed to fetch',
    'TypeError: NetworkError when attempting to fetch resource.'
  ],
});


Note:
Failed to fetch is also generated by CORS errors, please be mindful of that too. Also we decided to ignore errors with statusCode in between 400 to 426 using the beforeSend callback of sentry.

I spent days trying to find this error. Hope this helps somebody.

Originally I wrote this response on this page - https://forum.sentry.io/t/typeerror-failed-to-fetch-reported-over-and-overe/8447/2

Thank you



来源:https://stackoverflow.com/questions/43800998/why-do-fetch-errors-not-have-a-stacktrace-in-my-single-page-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!