5

我正在尝试从 API 获取公共 IP 地址,然后让该 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的家伙在这里,对我放轻松。

4

2 回答 2

5

目前您ninjaGetIp的不是 awaitable Promise

您可以尝试只返回一个Promise包装实现的新的,或者只是async在函数之前添加关键字。

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

异步示例

async 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'; 
                }
            }
        
    }
于 2019-01-25T01:36:00.493 回答
1

那是因为ninjaGetIp不可等待。您必须返回 aPromise才能返回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');
                }
            }
        });

    }

此外,您可以简化它并使用fetchwhich 返回一个承诺,而不是使用构建一个所需的所有代码XMLHttpRequest

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

TL;博士;

如果你想坚持使用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. 获取 API
  2. 异步
  3. 等待
于 2019-01-25T00:28:05.203 回答