最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Fetch API: Can 'await res.json()' fail after a completed request? - Stack Overflow

programmeradmin3浏览0评论

A fetch API request will only fail if there is a network or server error. So for example, if I execute the following code, assuming it went through the try block without an error, I will have a valid populated res.

try {
    const res = await fetch('/createurl', { 
        method: 'POST',
        body: 'testData',
        headers: {
            'Content-Type': 'application/json'
        }
    })

    if (res.ok) {
        alert('Resource created!')
    } else {
        alert('Error creating resource!')
    }

    flashResponseToUser(res)
} catch(e) {
    alert('A server or network error occurred during the request!')
}

I am handling res to show the users the necessary error or success message using the flashResponseToUser(res) function. Since res.json() returns a Promise, flashResponseToUser has to be an async function.

const flashResponseToUser = async(res) => {
    const jsonRes = await res.json() // Get data from response
    console.log(jsonRes)
}

I want to know:

  1. Why does res.json() return a Promise since at this point the response has already been received by the client?
  2. Under what conditions would the Promise returned by res.json() fail?
  3. Does the code within flashResponseToUser(res) also need to be wrapped within a try-catch block since I am using res.json()?

A fetch API request will only fail if there is a network or server error. So for example, if I execute the following code, assuming it went through the try block without an error, I will have a valid populated res.

try {
    const res = await fetch('/createurl', { 
        method: 'POST',
        body: 'testData',
        headers: {
            'Content-Type': 'application/json'
        }
    })

    if (res.ok) {
        alert('Resource created!')
    } else {
        alert('Error creating resource!')
    }

    flashResponseToUser(res)
} catch(e) {
    alert('A server or network error occurred during the request!')
}

I am handling res to show the users the necessary error or success message using the flashResponseToUser(res) function. Since res.json() returns a Promise, flashResponseToUser has to be an async function.

const flashResponseToUser = async(res) => {
    const jsonRes = await res.json() // Get data from response
    console.log(jsonRes)
}

I want to know:

  1. Why does res.json() return a Promise since at this point the response has already been received by the client?
  2. Under what conditions would the Promise returned by res.json() fail?
  3. Does the code within flashResponseToUser(res) also need to be wrapped within a try-catch block since I am using res.json()?
Share Improve this question edited Jan 14, 2020 at 18:01 philosopher asked Jan 14, 2020 at 7:12 philosopherphilosopher 1,1513 gold badges17 silver badges34 bronze badges 3
  • developer.mozilla.org/en-US/docs/Web/API/Body this will be able help you with those questions. – sshanzel Commented Jan 14, 2020 at 7:16
  • 1 @Siege21x I did read that but it still doesn't explain why res.json() returns a Promise instead of returned data directly. Also doesn't tell us under what conditions res.json() fails. – philosopher Commented Jan 14, 2020 at 7:19
  • answer for first question. answer for second question. – SuleymanSah Commented Jan 14, 2020 at 7:31
Add a comment  | 

1 Answer 1

Reset to default 20

Why does res.json() return a Promise since at this point the response has already been received by the client?

fetch returns a Response object. This indicates that the headers of the response have been received, but does not necessarily mean that the whole response has been received - imagine, for example, when you load a huge page. It's not exactly the same thing, but you'll receive the headers and the browser will start to load the response even though there's still more to download. The Response object provides the headers and a way to handle still-incoming data.

Under what conditions would the Promise returned by res.json() fail?

It might fail if the response wasn't in proper JSON format. For example, if the plain text of the response was Internal Server Error, which isn't JSON. Here's an example:

(async () => {
  const response = await fetch('data:,Internal%20Server%20Error');
  console.log('got response');
  try {
    await response.json();
  } catch(e) {
    console.log('error:', e.message);
  }
})();

Does the code within flashResponseToUser(res) also need to be wrapped within a try-catch block since I am using res.json()?

If you wanted to be perfectly safe, yes. But, in most situations, it's easiest just to catch in one place, where you can handle the error. Instead of handling possible errors at every step of the process, you might handle the error just once, in the consumer, eg:

const getInfo = async () => {
  const res = await fetch('/createurl', { 
    method: 'POST',
    body: 'testData',
    headers: {
      'Content-Type': 'application/json'
    }
  })

  if (!res.ok) {
    throw new Error(res.status);
  }
  return res.json();
};
getInfo()
  .then(flashResponseToUser)
  .catch(() => {
    alert('A server or network error occurred during the request!')
  })

(assuming that flashResponseToUser will never throw, if provided with an expected object. If flashResponseToUser might throw anyway, you can separate out the .catches to distinguish network errors from other runtime errors)

发布评论

评论列表(0)

  1. 暂无评论