ПОЛУЧИТЬ запрос после завершения запроса POST - PullRequest
0 голосов
/ 26 июня 2018

В моем проекте мне нужно зарегистрировать пользователя в БД (запрос POST) через пользовательские API.

Как только эта операция будет завершена, я хотел бы сделать GET-запрос, чтобы получить всех пользователей и передать вновь созданную информацию (например, id и другие) в следующее состояние (я разрабатываю игру с использованием инфраструктуры Phaser).

То, что я пытаюсь сделать, - это использовать обратный вызов в запросе post, чтобы затем вызвать другую функцию, которая снова извлекает всех игроков, но, конечно, это не работает, потому что это асинхронные операции (хотя я думал, что смогу решить это с помощью обратных вызовов).

Это мои 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);
}

Как убедиться, что GET-запрос выполняется только ПОСЛЕ того, что POST-запрос был выполнен?

EDIT

Я понял, что этот код никогда не выполняется, поэтому даже консольное сообщение не печатается:

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

Однако на этой странице они приводят пример, написанный таким образом. Что-то мне не хватает?

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

Я бы сделал ваш HttpRequest (запрос POST) синхронным. В настоящее время у вас есть xhttp.open("POST", "https://project.herokuapp.com/api/users",true);, который делает запрос асинхронным.

Если вы измените параметр true на false, ваши запросы приведут к зависанию POST-запроса до его завершения. Затем вы можете позвонить в Get Request как обычно.

0 голосов
/ 26 июня 2018

Вопрос. Вам нужно вызвать retrieveNewUser для выполнения "xhttp.send (input);"

Если нет, я бы предложил вам обернуть функцию saveNewUser в обещание. Обещания - это, по сути, более продвинутая форма обратных вызовов, позволяющая сделать асинхронный код более синхронным.

Итак, ваша функция 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);
});

Функция затем принимает обратный вызов в качестве параметра. Обратный вызов получает данные, которые были разрешены (в данном случае name ), и что-то делает с ними (в этом случае вызывает retrieveNewUser ).

Это гарантирует, что retrieveNewUser () не запустится до тех пор, пока не будет завершено действие saveNewUser.

0 голосов
/ 26 июня 2018

Вы можете рассмотреть возможность использования Promise, чтобы после завершения функции javascript вы могли получить состояние, а затем вызвать другую функцию.

Вы можете сослаться на этот ответ , я думаю, что его пример довольно ясен.

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.

Руки вверх 101

...