POST请求完成后的GET请求

时间:2018-06-26 19:39:57

标签: javascript post get xmlhttprequest

在我的项目中,我需要通过自定义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中提供了以这种方式编写的示例。有什么我想念的吗?

3 个答案:

答案 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请求挂起,直到完成。然后,您可以照常调用获取请求。