【问题标题】:GET request after a POST request is completePOST 请求完成后的 GET 请求
【发布时间】:2018-12-05 14:41:22
【问题描述】:

在我的项目中,我需要通过自定义 API 在数据库中注册一个用户(POST 请求)。

一旦该操作完成,我想发出 GET 请求以获取所有用户并将新创建的信息(例如 id 和其他信息)传递到下一个状态(我正在使用 Phaser 框架开发游戏)。

我想要做的是在发布请求中使用回调来调用另一个函数来再次检索所有玩家,但它当然不起作用,因为它们是异步操作(虽然我认为我可以通过回调解决)。

这是我的两个功能:

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

如何确保 GET 请求仅在 POST 完成后才执行?

编辑

我意识到这段代码永远不会执行,所以连控制台消息都没有打印出来:

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 中,他们提供了一个以这种方式编写的示例。有什么我遗漏的吗?

【问题讨论】:

  • “不起作用”到底是什么意思? 任何事情会发生吗?是否报告错误?您在浏览器“网络”控制台中看到了什么?
  • @Pointy 基本上创建了用户,但它从不调用retrieveNewUser 函数
  • 它是否记录 XHR 响应文本?控制台有错误吗?

标签: javascript post get xmlhttprequest


【解决方案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 来说是一个非常好的实践。

举起手来???

【讨论】:

  • 我已阅读该答案,但我发现的所有示例都集中在 GET --> POST 序列上,而不是相反。不幸的是,正如我在问题本身的评论中所写,retrieveNewUser 函数永远不会被执行。请提供一个清晰的例子吗?
【解决方案2】:

我会让您的 HttpRequest(POST 请求)同步。 您当前有 xhttp.open("POST", "https://project.herokuapp.com/api/users",true); 正在使请求异步。

如果您将true 参数更改为false,您的请求将导致POST 请求挂起直到完成。然后你可以像往常一样调用Get Request。

【讨论】:

  • 是否不推荐,尤其是关于用户体验问题,因为它会冻结整个 UI?
【解决方案3】:

问题。您是否需要调用retrieveNewUser 才能执行“xhttp.send(input);” ?

如果没有,我建议您将 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);
    }
})};

从那里,您可以通过链接承诺并运行以下语句以同步方式运行这两个函数:

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

then 函数将回调作为参数。回调接收已解析的数据(在本例中为 name)并对其进行处理(在本例中为调用 retrieveNewUser)。

这确保 retrieveNewUser() 在 saveNewUser 完成之前不会运行。

【讨论】:

    猜你喜欢
    • 2014-07-24
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多