简体   繁体   English

POST请求完成后的GET请求

[英]GET request after a POST request is complete

In my project, I need to register a user in the db (POST request) through custom APIs. 在我的项目中,我需要通过自定义API在db(POST请求)中注册用户。

Once that operation has been completed, I would like to make a GET request to get all users and pass the newly created information (eg id and others) to the next state (I am developing a game with the Phaser framework). 一旦该操作完成,我想发出GET请求以获取所有用户,并将新创建的信息(例如id和其他信息)传递到下一个状态(我正在使用Phaser框架开发游戏)。

What I am trying to do is to use the callback in the post request to then call the other function that retrieves all the players again, but of course it doesn't work because they are async operations (although I thought I could solve it through callbacks). 我想做的是在post请求中使用回调函数,然后调用另一个可再次检索所有玩家的函数,但是当然不起作用,因为它们是异步操作(尽管我认为我可以通过以下方式解决它:回调)。

These are my 2 functions: 这些是我的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);
    }
}

And the function that gets called inside: 而里面调用的函数:

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

How do you make sure that the GET request is executed only AFTER the POST one has been completed? 您如何确保仅在POST完成后才执行GET请求?

EDIT 编辑

I realized that this code is never executed, so even the console message is not printed: 我意识到此代码永远不会执行,因此即使控制台消息也不会打印:

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

However, in this page they provide an example written in such a way. 但是,在此页面中,他们提供了以这种方式编写的示例。 Is there something I am missing? 我有什么想念的吗?

You might consider using Promise, that way you can have a state after the javascript function complete and then you can call another function. 您可能会考虑使用Promise,这样您就可以在javascript函数完成后进入状态,然后再调用另一个函数。

you may refer to this answer , i think that his example is pretty clear. 您可以参考这个答案 ,我认为他的例子很清楚。

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

Please read the whole answer, he explain how to use with Promises, which is a really good practice for JavaScript. 请阅读整个答案,他解释了如何与Promises结合使用,这对于JavaScript来说确实是一个很好的实践。

Hands Up 😁👍🏼 举起手来😁👍🏼

Question. 题。 Do you need to call retrieveNewUser in order to execute "xhttp.send(input);" 为了执行“ xhttp.send(input);”,是否需要调用retrieveNewUser? ?

If not, I would suggest you wrap the saveNewUser function in a promise. 如果没有,我建议您将saveNewUser函数包装在Promise中。 Promises are basically a more advanced form of callbacks that allow you to make asynchronous code execute more synchronously. 基本上,Promise是回调的一种高级形式,它使您可以使异步代码更同步地执行。

So your saveNewUser function would look like this: 因此,您的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);
    }
})};

From there, you can run both functions in a synchronous manner by chaining the promises and running this statement: 从那里,您可以通过链接promises并运行以下语句,以同步方式运行这两个功能:

saveNewUser(name, password)
.then(function(name){
retrieveNewUser(name);
});

The then function takes a callback as a parameter. then函数将回调作为参数。 The callback receives the data that was resolved (in this case, name ) and does something with it (in this case, calls retrieveNewUser ). 回调接收已解析的数据(在本例中为name ),并对其执行某些操作(在本例中,调用retrieveNewUser )。

This ensures that retrieveNewUser () doesn't run until saveNewUser is finished. 这样可以确保saveNewUser完成之前, retrieveNewUser ()不会运行。

I would make your HttpRequest (POST request) synchronous. 我将使您的HttpRequest(POST请求)同步。 You currently have xhttp.open("POST", "https://project.herokuapp.com/api/users",true); 您当前有xhttp.open("POST", "https://project.herokuapp.com/api/users",true); which is making the request asynchronous. 这使得请求异步。

If you change the true parameter to false , your requests will cause the POST request to hang until complete. 如果将true参数更改为false ,则您的请求将导致POST请求挂起,直到完成。 Then you may call the Get Request as usual. 然后,您可以像往常一样调用“获取请求”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM