Fetch() 没有从服务器返回数据作为响应
Fetch() is not returning data from server in response
我在从服务器获取 return 任何数据时遇到问题,我似乎不太明白为什么。
我想也许在服务器发回任何 JSON 之前 promise 就解决了,所以我最近更新了我的模型以也利用 promises。我是 promises 和 fetch API 的新手,所以请多多包涵。
I am willing to revert back too callbacks and put my Player.find
and Player.create
methods back in
the Players.js
route and avoid promises on the server side altogether.
玩家模型(添加promise后)
// 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;
路由(添加promise后)
// 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
我得到:
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Response {type: "basic", url: "http://localhost:3000/api/players", status: 200, ok: true, statusText: "OK"…}
ReadableStream {}
当我在 postman 中测试我的 POST 端点 (http://localhost:3001/api/players
) 时,服务器响应一个包含我想要的数据的 JSON 对象。无论出于何种原因 client.createPlayer
都没有 return 来自服务器的数据。当然,这只是问题的一部分。
理论上,一旦我的 client.createPlayer
解析并且我调用 client.getPlayers
作为对 client.createPlayer
的回调,该方法应该 return 我想要的数据,包括新创建的播放器, 正确的?
然而情况似乎并非如此。
我做错了什么?
有趣的是,通过将 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
发出 re-render.
就会显示新玩家
我在从服务器获取 return 任何数据时遇到问题,我似乎不太明白为什么。
我想也许在服务器发回任何 JSON 之前 promise 就解决了,所以我最近更新了我的模型以也利用 promises。我是 promises 和 fetch API 的新手,所以请多多包涵。
I am willing to revert back too callbacks and put my
Player.find
andPlayer.create
methods back in thePlayers.js
route and avoid promises on the server side altogether.
玩家模型(添加promise后)
// 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;
路由(添加promise后)
// 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
我得到:
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Response {type: "basic", url: "http://localhost:3000/api/players", status: 200, ok: true, statusText: "OK"…}
ReadableStream {}
当我在 postman 中测试我的 POST 端点 (http://localhost:3001/api/players
) 时,服务器响应一个包含我想要的数据的 JSON 对象。无论出于何种原因 client.createPlayer
都没有 return 来自服务器的数据。当然,这只是问题的一部分。
理论上,一旦我的 client.createPlayer
解析并且我调用 client.getPlayers
作为对 client.createPlayer
的回调,该方法应该 return 我想要的数据,包括新创建的播放器, 正确的?
然而情况似乎并非如此。
我做错了什么?
有趣的是,通过将 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
发出 re-render.