【问题标题】:fetch gives an empty response bodyfetch 给出一个空的响应体
【发布时间】:2016-08-18 20:00:27
【问题描述】:

我有一个 react/redux 应用程序,我正在尝试向服务器发出一个简单的 GET 请求:

fetch('http://example.com/api/node', {
  mode: "no-cors",
  method: "GET",
  headers: {
    "Accept": "application/json"
  }
}).then((response) => {
  console.log(response.body); // null
  return dispatch({
    type: "GET_CALL",
    response: response
  });
})
.catch(error => { console.log('request failed', error); });

问题是.then() 函数中的响应正文是空的,我不知道为什么。我在网上检查了示例,看起来我的代码应该可以工作,所以我显然在这里遗漏了一些东西。 问题是,如果我在 Chrome 的开发工具中检查网络选项卡,就会发出请求并收到我正在寻找的数据。

有人能介绍一下这个吗?

编辑:

我尝试转换响应。

使用.text():

fetch('http://example.com/api/node', {
  mode: "no-cors",
  method: "GET",
  headers: {
    "Accept": "application/json"
  }
})
.then(response => response.text())
.then((response) => {
  console.log(response); // returns empty string
  return dispatch({
    type: "GET_CALL",
    response: response
  });
})
.catch(error => { console.log('request failed', error); });

.json():

fetch('http://example.com/api/node', {
  mode: "no-cors",
  method: "GET",
  headers: {
    "Accept": "application/json"
  }
})
.then(response => response.json())
.then((response) => {
  console.log(response.body);
  return dispatch({
    type: "GET_CALL",
    response: response.body
  });
})
.catch(error => { console.log('request failed', error); }); // Syntax error: unexpected end of input

查看 chrome 开发工具:

【问题讨论】:

    标签: javascript fetch-api


    【解决方案1】:

    我刚碰到这个。正如answer 中提到的,使用mode: "no-cors" 会给你一个opaque response,它似乎不会在正文中返回数据。

    不透明:对跨域资源的“no-cors”请求的响应。 Severely restricted.

    就我而言,我使用的是Express。在我安装cors for Express 并配置它并删除mode: "no-cors" 后,我得到了一个承诺。响应数据将在 Promise 中,例如

    fetch('http://example.com/api/node', {
      // mode: 'no-cors',
      method: 'GET',
      headers: {
        Accept: 'application/json',
      },
    },
    ).then(response => {
      if (response.ok) {
        response.json().then(json => {
          console.log(json);
        });
      }
    });
    

    【讨论】:

    • 对我来说,所需要的只是将.then(json => { 添加到我的response.json() 语句的末尾。谢谢!
    • @MikeKellogg 只是提醒一下,如果您想保持代码整洁,您可以 return response.json() 并将 .then(json=> 部分放在最后一个括号和分号之间。 ).then(json=>{});
    • 如果您离开域并使用相对URI,它似乎可以与no-cors一起使用
    • 我使用的是 AWS API Gateway,在我的 lambda 中,我在响应中缺少此标头 "Access-Control-Allow-Origin": "*"。添加并删除 no-cors 对我有用。
    • 对于那些希望打开no-cors 模式以试图绕过某些 CORS 限制的人,不幸的是,无法解析从这些类型的请求返回的不透明响应。我非常困惑,因为我可以在浏览器开发人员工具中清楚地看到正确的响应,但它从来没有通过我的代码。有关该主题的更多讨论可以在这里找到:stackoverflow.com/a/54906434/3513260
    【解决方案2】:

    您需要将response 转换为json,然后才能访问response.body

    来自docs

    fetch(url)
      .then(response => response.json())
      .then(json => {
        console.log('parsed json', json) // access json.body here
      })
    

    【讨论】:

    • 很好的答案,感谢您对文档的参考。文档还显示了如果您使用 JSON 以外的其他内容(例如文本)该怎么做 - 它可以显示相同的行为并且解决方案非常相似(使用 text() 而不是 json() )。
    【解决方案3】:

    这需要更改前端 JS 和后端发送的标头。

    前端

    删除提取选项中的"mode":"no-cors"

    fetch(
      "http://example.com/api/docs", 
      {
        // mode: "no-cors",
        method: "GET"
      }
    )
      .then(response => response.text())
      .then(data => console.log(data))
    

    后端

    当您的服务器响应请求时,请包含指定请求来源的 CORS 标头。如果您不关心来源,请指定* 通配符。

    原始响应应包含这样的标头。

    Access-Control-Allow-Origin: *
    

    【讨论】:

      【解决方案4】:

      您必须阅读响应的正文:

      fetch(url)
        .then(res => res.text()) // Read the body as a string
      
      fetch(url)
        .then(res => res.json()) // Read the body as JSON payload
      

      一旦您阅读了正文,您就可以对其进行操作:

      fetch('http://example.com/api/node', {
        mode: "no-cors",
        method: "GET",
        headers: {
          "Accept": "application/json"
        }
      })
        .then(response => response.json())
        .then(response => {
          return dispatch({
            type: "GET_CALL",
            response: response
          });
        })
      

      【讨论】:

      • 感谢您的回答!我试过了,但我仍然可以得到正确的响应。检查已编辑的问题。
      • @RazvanIlin 使用.json() 而不是.text()
      • 对不起,我刚刚意识到我在上一个示例中复制了错误的 sn-p。我实际上在那里使用json(),但我得到了语法错误,我认为它会被触发,因为它无法将响应转换为 json
      • 试过这个,它对我有用。 response.json() 创造了奇迹。一旦我有了它,我就可以 console.log 并得到我的回复。谢谢
      • 我仍然试图围绕这个no-cors 模式。我也有类似的情况。在这里使用解决方案的变体,no-cors fetch 似乎成功了……没有 x-origin 错误,在我的网络检查器中,我可以在预览和响应中看到数据。但我似乎无法访问传递给我的then 的响应对象中的数据。 json() text() 似乎都没有做太多。不透明的响应是否意味着它获取数据然后nulls 它所以完成后无法访问? :-/
      【解决方案5】:
      fetch("http://localhost:8988/api", {
              //mode: "no-cors",
              method: "GET",
              headers: {
                  "Accept": "application/json"
              }
          })
          .then(response => {
              return response.json();
          })
          .then(data => {
              return data;
          })
          .catch(error => {
              return error;
          });
      

      这对我有用。

      【讨论】:

        【解决方案6】:
        fetch("http://localhost:8988/api", {
            method: "GET",
            headers: {
               "Content-Type": "application/json"
            }
        })
        .then((response) =>response.json());
        .then((data) => {
            console.log(data);
        })
        .catch(error => {
            return error;
        });
        

        【讨论】:

        • 虽然此代码可能会回答 OP 的问题,但几句话的解释将有助于当前和未来的读者理解您的回复。
        • 这实际上与此处的其他答案非常相似。不确定 SO 的政策,但我不确定是否允许这样做
        • 只是不一样。 “内容类型”是唯一的。可惜它对我不起作用:(
        【解决方案7】:

        尝试使用response.json():

        fetch('http://example.com/api/node', {
          mode: "no-cors",
          method: "GET",
          headers: {
            "Accept": "application/json"
          }
        }).then((response) => {
          console.log(response.json()); // null
          return dispatch({
            type: "GET_CALL",
            response: response.json()
          });
        })
        .catch(error => { console.log('request failed', error); });
        

        【讨论】:

          【解决方案8】:

          在许多情况下,您需要在 express 节点应用程序中添加 bodyParser 模块。 然后在 app.use(express.static('www')); 下方的 app.use 部分中 添加这两行 app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json());

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-04-01
            • 1970-01-01
            • 2022-12-13
            • 2017-07-25
            • 2012-08-28
            • 2020-09-12
            • 2018-09-10
            • 1970-01-01
            相关资源
            最近更新 更多