提取给出一个空的响应主体


73

我有一个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开发工具中查看:

在此处输入图片说明


我无法fetch上班,所以我开始使用redux-api-middleware。当您发出请求时,您必须以类似于此处建议的方式将响应转换为json:
Razvan Ilin

Answers:


159

我刚遇到这个。就像在这个答案中提到的那样,usingmode: "no-cors"将为您提供一个opaque response,似乎不会在体内返回数据。

opaque:跨源资源的“ no-cors”请求的响应。 严格限制

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

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

3
对我而言,所需要做的只是添加.then(json => {response.json()声明的末尾。谢谢!
迈克·凯洛格

2
@MikeKellogg提醒您,如果要保持代码整洁,可以return response.json()将其.then(json=>放在最后一个括号和分号之间。).then(json=>{});
拉兹万·伊林

看来,如果您离开网域并使用相对的URI,则可以使用它no-cors
Danny'365CSI'Engelman


6

您必须阅读响应的正文:

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

感谢你的回答!我尝试过,但仍然可以得到正确的答复。检查已编辑的问题。
Razvan Ilin

@RazvanIlin使用.json()代替.text()
Florent

1
抱歉,我刚刚意识到我在上一个示例中复制了错误的代码段。我当时实际上在使用json(),但是我收到语法错误,我认为它会被解雇,因为它无法将响应转换为json
Razvan Ilin

尝试了一下,它为我工作。response.json()做了魔术。一旦有了它,我就可以console.log并得到我的回应。谢谢
Hanmaslah '17

3
仍然试图绕过这种no-cors模式。我也有类似情况。在这里使用各种解决方案,无取芯似乎成功了……没有x起源错误,并且在我的网络检查器中,我可以在“预览和响应”中查看数据。但是我似乎无法访问传递给我的的响应对象中的数据thenjson() text()似乎都没做多。不透明的响应是否意味着先获取数据然后将其保存null,以便在完成后无法访问?:-/
jmk2142 '17

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

这对我有用。


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

2
尽管此代码可以回答OP的问题,但仅需几句解释就能帮助当前和将来的读者理解您的回答。
汤姆

这实际上与这里的其他答案非常相似。不确定SO的政策,但我不确定这是否允许
Razvan Ilin

只是不一样。“内容类型”是唯一的。不幸的是,它对我没有用:(
迈克尔

2

尝试使用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); });

1

这需要更改前端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: *

0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.