在我的项目中,我需要通过自定义API在数据库(POST请求)中注册用户。
一旦操作完成,我想发出GET请求以获取所有用户,并将新创建的信息(例如id和其他信息)传递到下一个状态(我正在使用Phaser框架开发游戏)。
我想做的是在发布请求中使用回调函数,然后调用另一个再次检索所有玩家的函数,但是当然不起作用,因为它们是异步操作(尽管我认为我可以通过回调解决)。
这些是我的2个功能:
saveNewUser: function(name, password){
var self = this;
if(name && password){
// create new calibration data for the current user
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "https://project.herokuapp.com/api/users",true);
xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
var input = JSON.stringify({
"name": name,
"password": password,
});
xhttp.onreadystatechange = function() {//Call a function when the state changes.
if(xhttp.readyState == 4 && xhttp.status == 200) {
console.log(xhttp.responseText);
self.retrieveNewUser(name);
}
};
xhttp.send(input);
} else {
self.errorMessage.visible = true;
// make text become not visible again after few seconds
self.time.events.add(Phaser.Timer.SECOND * 3, function () {
self.errorMessage.visible = false;
}, this);
}
}
以及在内部调用的函数:
retrieveNewUser: function (name) {
var self = this;
// save user details in the global variables, get user after registration in db
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://duchennegame.herokuapp.com/api/users', true);
xhr.onload = function () {
var users = JSON.parse(xhr.responseText);
if (xhr.readyState == 4 && xhr.status == "200") {
var userFound = false;
users.forEach(function(user){
if(user.name === name){
// save user details in the global variables
self.game.global.currentUser = user;
self.state.start('welcome');
userFound = true;
}
});
// if user has not been found / wrong password, display error message
if(!userFound){
self.errorMessage.setText('Problem in retrieving the current user');
self.errorMessage.visible = true;
// make text become not visible again after few seconds
self.time.events.add(Phaser.Timer.SECOND * 3, function () {
self.errorMessage.visible = false;
}, self);
}
} else {
console.error(users);
}
};
xhr.send(null);
}
如何确保仅在POST完成后才执行GET请求?
编辑
我意识到此代码永远不会执行,因此即使控制台消息也不会打印:
xhttp.onreadystatechange = function() {//Call a function when the state changes.
if(xhttp.readyState == XMLHttpRequest.DONE && xhttp.status == 200) {
console.log(xhttp.responseText);
self.retrieveNewUser(name);
}
};
但是,它们在this page中提供了以这种方式编写的示例。有什么我想念的吗?
答案 0 :(得分:1)
您可能会考虑使用Promise,这样您就可以在javascript函数完成后进入状态,然后再调用另一个函数。
您可以参考此answer,我认为他的例子很清楚。
function makeRequest (method, url, done) {
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
done(null, xhr.response);
// CALLBACK ON SUCCESS
};
xhr.onerror = function () {
done(xhr.response);
//CALLBACK ON ERROR
};
xhr.send();
}
// And we'd call it as such:
makeRequest('GET', 'http://example.com', function (err, datums) {
if (err) { throw err; }
console.log(datums);
});`
请阅读全部答案,他解释了如何与Promises结合使用,这对于JavaScript来说是一个非常好的实践。
动手
答案 1 :(得分:1)
问题。为了执行“ xhttp.send(input);”,是否需要调用retrieveNewUser? ?
如果没有,我建议您将saveNewUser函数包装在Promise中。基本上,Promise是回调的一种高级形式,它使您可以使异步代码更同步地执行。
因此,您的saveNewUser函数将如下所示:
saveNewUser: function(name, password){
var self = this;
//Returns Promise Object
return new Promise(function(resolve, reject) {
if(name && password){
// create new calibration data for the current user
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "https://project.herokuapp.com/api/users",true);
xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
var input = JSON.stringify({
"name": name,
"password": password,
});
xhttp.onreadystatechange = function() {//Call a function when the state changes.
if(xhttp.readyState == 4 && xhttp.status == 200) {
console.log(xhttp.responseText);
//This line of code essentially acts as a return statement
resolve(name);
}
};
xhttp.send(input);
} else {
self.errorMessage.visible = true;
// make text become not visible again after few seconds
self.time.events.add(Phaser.Timer.SECOND * 3, function () {
self.errorMessage.visible = false;
}, this);
}
})};
从那里,您可以通过链接promises并运行以下语句以同步方式运行这两个功能:
saveNewUser(name, password)
.then(function(name){
retrieveNewUser(name);
});
然后函数将回调作为参数。回调接收已解析的数据(在本例中为 name ),并对其进行处理(在本例中,调用 retrieveNewUser )。
这可确保 retrieveNewUser ()在saveNewUser完成之前不会运行。
答案 2 :(得分:0)
我将使您的HttpRequest(POST请求)同步。
当前,您有xhttp.open("POST", "https://project.herokuapp.com/api/users",true);
正在使请求异步。
如果将true
参数更改为false
,则您的请求将导致POST请求挂起,直到完成。然后,您可以照常调用获取请求。