2016-05-13 274 views
1

我想从onreadystatechange AJAX调用返回一个值...我发现这个网页:stackoverflow link。我虽然我有它的工作,但意识到添加或删除fn函数没有区别。下面的代码工作:从onreadystatechange返回值与回调

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

这一切工作正常,但是这不是我的目标,我想一个函数username_is_available()如果用户名确实可以返回true。 相反,在这里我发生了一个动作(innerHTML被改变)。如果我尝试在匿名函数中进行返回,则会得到与直接在onreadystatechange中返回结果相同的结果:var unasigned

对于那些即将点击'重复线程'的人,此isn重复的。 我一直在它5小时以上

回答

2

不幸的是,由于该过程,以确定是否采取了用户名是异步的,没有办法简单地从函数调用返回的truefalse的值。你所能做的就是使用专门为此目的设计的语言特性来设置类似于你现在所拥有的东西(回调)。

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

这依赖于availablity.php返回truefalse为文本,这是resolve调用之前转换为布尔。

今后,当ES7 + asyncawait指令是可用的,使用的承诺将是像这样简单(注意await关键字):

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

编辑 :如果你不能使用ES6或承诺,它会回到良好的回调状态!

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

在你最后的例子中,我认为'taken'应该是'available'。 –

+0

您为'taken'指定一个值并使用未声明的变量'available'。变量名'taken'应该是'available',因为它从一个函数中接收一个布尔值,其中包含短语'is_available'。 –

+0

@PatrickRoberts良好的发现,我被抓住了第一个答案的嗡嗡声,疯狂地在文本框中编写代码,而不是像我平时所做的那样编写适当的编辑器和粘贴。谢谢! – Scott

0

我一直在与观察员一起玩耍,作为承诺的替代方案。我建立了一个an example in plnkr来展示它如何工作。我想在你的情况是这样的:

function Producer() { 
    this.listeners = []; 
} 

Producer.prototype.add = function(listener) { 
    this.listeners.push(listener); 
}; 

Producer.prototype.remove = function(listener) { 
    var index = this.listeners.indexOf(listener); 
    this.listeners.splice(index, 1); 
}; 

Producer.prototype.notify = function(message) { 
    this.listeners.forEach(function(listener) { 
     listener.update(message); 
    }); 
}; 

var notifier = new Producer; 

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

var username_is_available = { 
    update: function(returned_value) { 
     var username = document.getElementById('username').value; 
     if (returned_value == 'true') { 
      document.getElementById('username_err').innerHTML = 'Taken'; 
     } else { 
      document.getElementById('username_err').innerHTML = 'Available'; 
     };   
    } 
} 

notifier.add(username_is_available); 
get_data("username", username); 

注意Producer代码可以重复使用,你会做一个新的实例为其他Ajax /观察到的请求。