提取给出一个空响应主体

我有一个 response/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 开发工具:

enter image description here

184438 次浏览

You must read the response's body:

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


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

Once you've read the body you will be able to manipulate it:

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

You will need to convert your response to json before you can access response.body

From the docs

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

Try to use 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); });

I just ran into this. As mentioned in this answer, using mode: "no-cors" will give you an opaque response, which doesn't seem to return data in the body.

opaque: Response for “no-cors” request to cross-origin resource. Severely restricted.

In my case I was using Express. After I installed cors for Express and configured it and removed mode: "no-cors", I was returned a promise. The response data will be in the promise, e.g.

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

This works for me.

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

In many case you will need to add the bodyParser module in your express node app. Then in your app.use part below app.use(express.static('www')); add these 2 lines app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json());

This requires changes to the frontend JS and the headers sent from the backend.

Frontend

Remove "mode":"no-cors" in the fetch options.

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

Backend

When your server responds to the request, include the CORS headers specifying the origin from where the request is coming. If you don't care about the origin, specify the * wildcard.

The raw response should include a header like this.

Access-Control-Allow-Origin: *

in my case, it was not cors. For some reason, the client got an empty response body if fetch was invoked from the child component, as soon as I moved the data fetching to the root App component the client got the proper response body. I don't know why, just went with it. If someone could explain it, that would be great.