Async / Await, возвращаемая переменная не определена после XHR-запроса - PullRequest
0 голосов
/ 25 января 2019

Я пытаюсь получить публичный IP-адрес из API, а затем этот IP-адрес используется в другой функции (ninjaUniqueVisitorRequest()).

У меня есть следующий код:

function ninjaGetIp() {
    var ipRequest = new XMLHttpRequest();
    ipRequest.open('GET', "https://api.ipify.org?format=jsonp=", true);
    ipRequest.send();
    ipRequest.onload = function () {
        if (ipRequest.status >= 200 && ipRequest.status < 400) { // If response is all good...
            return ipRequest.responseText;
        } else {
            console.log('There was an error retrieving the public IP.');
            return '127.0.0.1'; 
        }
    }
}

async function ninjaUniqueVisitorRequest() {
    // var ninjaSiteUuid = ninjaGetSiteUuid();
    // var ninjaFingerprint = await ninjaGetFingerprint();
    var ninjaPublicIp = await ninjaGetIp();
    console.log(ninjaPublicIp);
}

В настоящее время, когда я запускаю ninjaUniqueVisitorRequest();, console.log(ninjaPublicIp); возвращает undefined.

Я вроде понимаю, что он возвращается сразу же, пока запрос не был сделан, однако это то, что я думал, что исправлял с помощью async/await.

Любые идеи приветствуются! Парень из PHP здесь, смирись со мной.

Ответы [ 2 ]

0 голосов
/ 25 января 2019

В настоящее время ваш ninjaGetIp не является ожидаемым Promise.

Вы можете попробовать просто вернуть новый Promise, который обернет реализацию.

function ninjaGetIp() {
    return new Promise(function (resolve, reject) {
        var ipRequest = new XMLHttpRequest();
        ipRequest.open('GET', "https://api.ipify.org?format=jsonp=", true);
        ipRequest.send();
        ipRequest.onload = function () {
            if (ipRequest.status >= 200 && ipRequest.status < 400) { // If response is all good...
                return resolve(ipRequest.responseText);
            } else {
                console.log('There was an error retrieving the public IP.');
                return resolve('127.0.0.1'); 
            }
        }
    });

}
0 голосов
/ 25 января 2019

Это потому, что ninjaGetIp не является ожидаемым.Вы должны вернуть Promise, чтобы иметь возможность await.

   async function ninjaGetIp() {
        return new Promise( (resolve, reject) => {
            var ipRequest = new XMLHttpRequest();
            ipRequest.open('GET', "https://api.ipify.org?format=jsonp=", true);
            ipRequest.send();
            ipRequest.onload = () => {
                if (ipRequest.status >= 200 && ipRequest.status < 400) { // If response is all good...
                    resolve(ipRequest.responseText);
                } else {
                    console.log('There was an error retrieving the public IP.');
                    reject('127.0.0.1');
                }
            }
        });

    }

Кроме того, вы можете упростить его и использовать fetch, который возвращает обещание вместо использования всего кода, необходимого длясоздайте XMLHttpRequest:

async function ninjaGetIp() {
    return fetch('https://api.ipify.org?format=jsonp=');
}

TL; DR;

Если вы хотите придерживаться XMLHttpRequest, я бы создал оболочку для него, потому чтоэто много избыточного кода: Вот пример:

class HttpClient {
    constructor(){}
    async get(url) {
        return new Promise( (resolve, reject) => {
            const xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = (evt) => {
                if (evt.currentTarget.readyState === 4 && evt.currentTarget.status === 200) {
                    try {
                        const response = JSON.parse(evt.currentTarget.response);
                        resolve(response);
                    } catch (exception) {
                        reject(exception);
                    }
                }
            };
            xhttp.open('GET', url, true);
            xhttp.send();
        });
    }
    async post(url, data) {
        return new Promise( (resolve, reject) => {
            const xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = (evt) => {
                if (evt.currentTarget.readyState === 4 && evt.currentTarget.status === 200) {
                    try {
                        const response = JSON.parse(evt.currentTarget.response);
                        resolve(response);
                    } catch (exception) {
                        reject(exception);
                    }
                }
            };
            xhttp.open('POST', url, true);
            xhttp.send(data);
        });
    }
}

Использование

const httpClient = new HttpClient();
const data = await httpClient.get('some url');
  1. Fetch API
  2. Async
  3. Await
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...