【问题标题】:fetch response.json() and response.status获取 response.json() 和 response.status
【发布时间】:2018-04-26 07:20:35
【问题描述】:

这是使用body.json() 并获取状态码的唯一方法吗?

let status;

return fetch(url)
    .then((response => {
         status = response.status;
         return response.json()
     })
    .then(response => {
        return {
            response: response,
            status: status
        }
    });

这不起作用,因为它在响应字段中返回了一个承诺:

.then((response)=> {return {response: response.json(), status: response.status}})

【问题讨论】:

  • return {'response': resp.json(), 'status': resp.status} 有什么问题?

标签: javascript promise fetch


【解决方案1】:

上周我也遇到了同样的问题。 .json 方法向解析后的 JSON 返回一个承诺,而不是解析后的 JSON 本身。如果你想同时访问响应和解析的 JSON,你需要使用这样的嵌套闭包:

fetch(url)
    .then(response => {
        response.json().then(parsedJson => {
            // code that can access both here
        })
    });

或者,您可以使用async/await 语法:

async function fetchTheThing() {
    const response = await fetch(url);
    const parsedJson = await response.json();

    // code that can access both here
}

当然,您需要检查错误,可以通过对 Promise 的 .catch(...) 调用或带有 async 函数的 try...catch 块。您可以创建一个处理 JSON 和错误情况的函数,然后将其重用于所有提取。例如,像这样:

function fetchHandler(response) {
    if (response.ok) {
        return response.json().then(json => {
            // the status was ok and there is a json body
            return Promise.resolve({json: json, response: response});
        }).catch(err => {
            // the status was ok but there is no json body
            return Promise.resolve({response: response});
        });

    } else {
        return response.json().catch(err => {
            // the status was not ok and there is no json body
            throw new Error(response.statusText);
        }).then(json => {
            // the status was not ok but there is a json body
            throw new Error(json.error.message); // example error message returned by a REST API
        });
    }
}

我认为这不是最好的设计模式,但希望这能阐明 fetch API 的工作原理。

【讨论】:

  • 注意:我曾经在生产中使用过这样的解决方案,但它是用于调用我自己制作的后端 API 的小应用程序。如果您的用例不是微不足道的,则可能有更好的模式可供遵循。
  • 有趣的模式可以在这里找到:danlevy.net/you-may-not-need-axios
【解决方案2】:

对我来说,使用两个 'then' 似乎没有必要。

async/await 可以很容易地完成工作。

    fetch('http://test.com/getData')
      .then( async (response) => {

        // get json response here
        let data = await response.json();
        
        if(response.status === 200){
         // Process data here
        }else{
         // Rest of status codes (400,500,303), can be handled here appropriately
        }

      })
      .catch((err) => {
          console.log(err);
      })

【讨论】:

  • 这绝对是最干净的解决方案。
【解决方案3】:

我认为最简洁的方法是使用您需要的部分创建一个 Promise.all()。

.then(response => Promise.all([Promise.resolve(response.ok), response.text()]))

可以写成更短的

.then(response => Promise.all([response.ok, response.text()]))

promise 返回一个包含所有结果的数组

.then(data => ({ status: data[0], response: data[1] }))

【讨论】:

    【解决方案4】:

    您的状态在第二个then 中不可见。您可以在单个 then 中获取这两个属性。

    json() 向您返回一个新的 Promise,因此您需要在该函数结果的 then 内创建您的对象。如果你从一个函数返回一个 Promise,它将被实现并返回实现的结果——在我们的例子中是对象。

    fetch("https://jsonplaceholder.typicode.com/posts/1")
    .then(r =>  r.json().then(data => ({status: r.status, body: data})))
    .then(obj => console.log(obj));

    【讨论】:

    • response.body 是一个可读流。 response.json 是一种向对象返回承诺的方法。
    • 亲爱的主,ajax 做得更好
    • @NikhilVJ 你介意发布一个等效的仅 ajax 响应吗?
    【解决方案5】:

    你试过了吗?

    return fetch(url)
        .then((r)=> {return {response: r.json(), status: r.status}})
    

    【讨论】:

    • 我试过了。问题是 r.json() 是一个承诺,像这样返回它意味着我在响应字段中得到了一个承诺。
    • 我认为@Suren Srapyan 是最好的解决方案
    猜你喜欢
    • 2017-07-08
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-18
    • 2021-07-05
    相关资源
    最近更新 更多