通过回调从 onreadystatechange 返回值

Iva*_*van 1 javascript callback onreadystatechange

我正在尝试从 onreadystatechange AJAX 调用返回一个值...我找到了此页面:stackoverflow 链接。我虽然可以正常工作,但意识到添加或删除 fn 函数没有什么区别。以下代码有效:

username_is_available();

function username_is_available() {
  var username = document.getElementById('username').value;

  get_data('username', username, function(returned_value) {
   if (returned_value == 'true') {
     document.getElementById('username_err').innerHTML = 'Taken';
    } else {
     document.getElementById('username_err').innerHTML = 'Available';
    };
  });
}

function get_data(data_type, data, fn) {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function() {
  if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
    fn(xmlhttp.responseText);
  }
};
  xmlhttp.open("GET", "availability.php?" + data_type + "=" + data, true);
  xmlhttp.send();
}
Run Code Online (Sandbox Code Playgroud)

一切正常,但这不是我的目标,我想要一个函数 username_is_available() ,如果用户名确实可用,它返回 true 。相反,这里发生了一个操作(innerHTML 被更改)。如果我尝试在匿名函数中返回,我会得到相同的结果,就像我直接从 onreadystatechange 内部返回它一样: var unsigned

Sco*_*ott 5

不幸的是,由于确定用户名是否被采用的过程是异步的,因此无法简单地从函数调用返回值truefalse从函数调用中返回值。您可以做的是使用专门为此目的而设计的语言功能来设置类似于您现在所拥有的内容(回调)。

Promise就是这些功能之一。

用法大致如下:

function username_is_available(username) {
    return new Promise(resolve => {
        get_data("username", username, resolve);
    });
}

function get_data(data_type, data, fn) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            fn(xmlhttp.responseText == "true");
        }
    };
    xmlhttp.open("GET", "availability.php?" + data_type + "=" + data, true);
    xmlhttp.send();
}

// Usage:
username_is_available("Ivan").then(available => {
    let text = available ? "Available" : "Taken";
    document.getElementById("username_err").innerHTML = text;
});
Run Code Online (Sandbox Code Playgroud)

这依赖于以文本形式availablity.php返回trueand ,在调用false之前将其转换为布尔值。resolve

将来,当 ES7+asyncawait指令可用时,使用 Promise 将像这样简单(注意关键字await):

let available = await username_is_available("Ivan");
let text = available ? "Available" : "Taken";
document.getElementById("username_err").innerHTML = text;
Run Code Online (Sandbox Code Playgroud)

编辑:如果你不能使用 ES6 或 Promise,那么它又回到了好的回调!

function username_is_available(username, callback) {
    get_data("username", username, callback);
}

function get_data(data_type, data, fn) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            fn(xmlhttp.responseText == "true");
        }
    };
    xmlhttp.open("GET", "availability.php?" + data_type + "=" + data, true);
    xmlhttp.send();
}

// Usage:
username_is_available("Ivan", function(available) {
    var text = available ? "Available" : "Taken";
    document.getElementById("username_err").innerHTML = text;
});
Run Code Online (Sandbox Code Playgroud)