Fetch() 没有从服务器返回数据作为响应
Posted
技术标签:
【中文标题】Fetch() 没有从服务器返回数据作为响应【英文标题】:Fetch() is not returning data from server in response 【发布时间】:2017-06-05 00:02:31 【问题描述】:我的 fetch 从服务器返回任何数据时遇到问题,我似乎不太明白为什么。
我认为在服务器发回任何 JSON 之前,promise 可能已经解决了,所以我最近更新了我的模型以使用 promises。我对 promises 和 fetch API 不熟悉,所以请多多包涵。
我也愿意恢复回调并将我的
Player.find
和Player.create
方法放回Players.js
路由并完全避免服务器端的承诺。
玩家模型(添加承诺后)
// require mongoose for data modeling
import mongoose from 'mongoose';
import Q from 'q';
const Schema = mongoose.Schema;
// define player schema
const PLAYER_SCHEMA = new Schema(
name: String,
score: Number
);
PLAYER_SCHEMA.statics.createPlayer = (name, score) =>
const deferred = Q.defer();
Player.create(
name,
score,
, (error, player) =>
if (error)
deferred.reject(new Error(error));
deferred.resolve(player);
);
return deferred.promise;
PLAYER_SCHEMA.statics.getPlayers = () =>
const deferred = Q.defer();
Player.find()
.sort(
score: 'desc'
)
.limit(5)
.exec((error, players) =>
if (error)
deferred.reject(new Error(error));
deferred.resolve(players);
);
return deferred.promise;
let Player = mongoose.model('Player', PLAYER_SCHEMA);
// first param is the singular name for the collection,
// mongoose automatically looks for the plural version
// so our db will have a 'players' collection
export default Player;
路线(添加承诺后)
// dependencies
import express from 'express';
import Player from '../models/player';
const ROUTER = express.Router();
ROUTER.post('/', (req, res) =>
const name = req.body.name;
const score = req.body.score;
const promise = Player.createPlayer(name, score);
promise.then((response) =>
res.status(201).json(response);
).catch((err) =>
res.send(err)
);
);
ROUTER.get('/', (req, res) =>
const promise = Player.getPlayers();
promise.then((response) =>
console.log(response);
res.status(200).json(response);
).catch((err) =>
res.send(err)
);
);
export default ROUTER;
在 Postman 中测试这些端点可以正常工作,所以我认为问题不在于服务器。
这是我怀疑我有问题的地方。
Client.js(存储 AJAX 方法的地方)
function createPlayer(playerData, onError, cb)
return fetch('/api/players',
method: 'post',
body: JSON.stringify(playerData),
headers:
'Accept': 'application/json',
'Content-Type': 'application/json',
,
).then(checkStatus)
.then(cb)
.catch(onError);
function getPlayers(success, onError)
return fetch('/api/players',
headers:
'Accept': 'application/json',
'Content-Type': 'application/json',
,
).then(checkStatus)
.then(parseJSON)
.then(success)
.catch(onError);
function checkStatus(response)
if (response.status >= 200 && response.status < 300)
return response;
else
const error = new Error(`HTTP Error $response.statusText`);
error.status = response.statusText;
error.response = response;
throw error;
function parseJSON(response)
return response.json();
const Client =
createPlayer,
getPlayers
;
export default Client;
App.jsx(省略了很多代码)
//所有其他代码省略
const playerData =
name,
score: this.state.totalScore,
;
client.createPlayer(playerData,
(err) =>
// TODO: improve error message
console.log(err);
,
client.getPlayers((data) =>
// array of objects containing all but most recent entry
console.log(data);
this.setState(
inputScreen: false, // hide the input screen
highScoreScreen: true, // show the high score screen
yeti: yetiWin,
highScores: [...this.state.highScores, ...data],
);
, (err) =>
// TODO: improve this error message
console.log(err);
)
);
//所有其他代码省略
数据变量从不包含新创建的玩家,但它确实包含其他玩家。因此创建和读取操作在服务器端进行。当我将App.jsx
修改为如下内容时:
App.jsx(试用版)
const playerData =
name,
score: this.state.totalScore,
;
client.createPlayer(playerData,
(err) =>
// TODO: improve error message
console.log(err);
,
(res) =>
// should contain something like:
//
// "__v": 0,
// "_id": "5881922f441fda40ccc52f83",
// "name": "player name",
// "score": "123"
//
// right?
console.log(res.json());
console.log(res);
console.log(res.body);
);
当我登录 res.json
res
和 res.body
时,我得到:
承诺[[PromiseStatus]]:“待定”,[[PromiseValue]]:未定义
响应type: "basic", url: "http://localhost:3000/api/players", status: 200, ok: true, statusText: "OK"…
可读流
当我在邮递员中测试我的 POST 端点 (http://localhost:3001/api/players
) 时,服务器会使用包含我想要的数据的 JSON 对象进行响应。无论出于何种原因,client.createPlayer
都不会从服务器返回数据。当然,这只是问题的一部分。
理论上,一旦我的client.createPlayer
解析并调用client.getPlayers
作为client.createPlayer
的回调,该方法应该返回我想要的数据,包括新创建的播放器,对吧?
但似乎并非如此。
我做错了什么?
【问题讨论】:
这个http://localhost:3001
看起来很可疑......我认为http://localhost:3001
也是发出请求的页面的加载位置,而不是来自像http://localhost:80
这样的不同主机或其他东西 - 我可以在 fetch 中看到您的 URL 是 '/api/players'
所以,这是实际代码,您没有删除任何内容只是为了问题,这不是“跨源”请求,是吗?
@JaromandaX 我正在使用 create-react-app,因此客户端服务器在 localhost:3000 上运行,而 express 服务器在 localhost:3001 上运行。客户端设置为代理对 localhost:3001 的请求。
好的 - 只是确保这不是 CORS 问题
【参考方案1】:
有趣的是,通过将App.jsx
中的代码更改为以下代码,我能够产生我想要的结果。但是,我不会将我的答案标记为正确的解决方案,因为我不完全理解为什么此更改会起作用。
如果有人想插话并解释为什么现在这样有效,我很想听听原因。
App.jsx(固定)
// all other code omitted
client.createPlayer(playerData, (err) =>
console.error(err);
, (data) =>
this.setState(
highScores: [...this.state.highScores, ...data],
);
);
client.getPlayers((data) =>
this.setState(
inputScreen: false, // hide the input screen
highScoreScreen: true, // show the high score screen
yeti: yetiWin,
highScores: [...this.state.highScores, ...data],
);
, (err) =>
console.error(err);
);
// all other code omitted
您会注意到我不再调用client.getPlayers
作为对client.createPlayer
的成功回调。最重要的是,我使用来自client.createPlayer
的返回数据并将其添加到状态中作为备用,以防client.createPlayer
方法在client.getPlayers
方法之前没有完成。这将确保在setState
发出重新渲染时显示新播放器。
【讨论】:
以上是关于Fetch() 没有从服务器返回数据作为响应的主要内容,如果未能解决你的问题,请参考以下文章