我目前正在编写JavaScript并且对回调感到困惑。我发现它不是一种内置函数,但是...... 我现在正在阅读O'Relly JavaScript第5版,它显示了类似下面的示例代码:
getText = function(url, callback) // How can I use this callback?
{
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (request.readyState == 4 && request.status == 200)
{
callback(request.responseText); // Another callback here
}
}
request.open('GET', url);
request.send();
}
基本上,我认为我不理解callback
的一般概念......有人可以写一个示例代码来利用上面的callback
吗?
答案 0 :(得分:46)
回调非常简单和漂亮!由于AJAX调用的性质,您不会阻止脚本的执行,直到您的请求结束(然后它将是同步的)。回调只是一个指定处理响应的方法,一旦它返回到您的方法。
由于javascript方法是第一类对象,因此可以像变量一样传递它们。
所以在你的例子中
getText = function(url, callback) // How can I use this callback?
{
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (request.readyState == 4 && request.status == 200)
{
callback(request.responseText); // Another callback here
}
};
request.open('GET', url);
request.send();
}
function mycallback(data) {
alert(data);
}
getText('somephpfile.php', mycallback); //passing mycallback as a method
如果您执行上述操作,则表示您将mycallback
作为处理响应(回调)的方法传递。
修改强>
虽然这里的例子没有说明回调的正确好处(你可以简单地将警报放在onReadyStateChange函数中!),但可重用性肯定是一个因素。
你必须记住,重要的是JS方法是第一类对象。这意味着您可以像对象一样传递它们并将它们附加到各种事件中。当事件触发时,将调用附加到这些事件的方法。
执行request.onreadystatechange = function(){}
时,您只需在相应的事件触发时指定要调用的方法。
这里很酷的是这些方法可以重复使用。假设您有一个错误处理方法,该方法会弹出警报,并在AJAX请求中的404情况下填充HTML页面中的某些字段。
如果你不能指定回调或传递方法作为参数,你必须一遍又一遍地编写错误处理代码,但你要做的就是将它作为回调和所有错误处理分配将一次排序。
答案 1 :(得分:17)
首先,我建议阅读回调内容。 Here是一个开始。
回调在异步编程中广泛使用。如果您不希望在(可能)长时间运行的操作完成之前阻塞,则解决问题的方法之一是将操作委派给将为您执行此操作的人员。这提出了一个问题:你如何能够判断操作何时完成,以及如何获得结果?
一种解决方案是将工作委托给其他人,并且不时地从正常工作中抽出一些时间来问“我给你做的工作了吗?”。如果是这样,请以某种方式获得结果,然后离开。问题解决了。
这种方法的问题在于它不会让您的生活更轻松。你现在被迫每隔一段时间就会问一次,你不会知道操作是否已经完成(但只有下次你记得要问)。如果您忘记提问,您将从不收到通知。
更好的解决方案是回调:委派工作时,提供一个功能。实际上做工作的代码然后承诺在工作完成后立即调用该函数。你现在可以忘记所有这些东西,并且知道当工作完成后,你的回调将被调用。不久,不迟。
在这种特定情况下,callback
是您向getText
提供的一种功能,允许它与您通信。你实际上在说“为我做这项工作,当你完成后,这是一个让你打电话告诉我的功能”。
getText
实际上只在XMLHttpRequest
(XHR)完成时选择使用此回调,同时它“让你知道”它会将HTTP响应的内容传递给你好吧(所以你可以根据这些信息采取行动)。
但是请花点时间阅读代码。它存储给request.onreadystatechange
的价值是多少? request.onreadystatechange
的目的是什么?
答案是request.onreadystatechange
可以填充回调。实际上,XHR为您提供了一种为其提供回调的方法,并且只要底层HTTP请求的状态发生变化,它就会“回拨”。
getText
是一个在之上构建抽象的函数:它插入自己的回调(一个匿名函数 - 我将其称为“inner “)在那里并接受来自你的另一个回调(参数 - 我将其称为”outer“)。当内部回调(记住:每当状态改变时被调用)检测到状态是“完成”(值4
的含义)并且HTTP响应状态代码是200(这意味着“OK”) ),它调用外部回调让getText
的用户知道结果。
我希望我有道理。 :)
答案 2 :(得分:1)
我个人更喜欢使用Event Listener而不是回调。
使用Listeners非常方便,特别是当您愿意一次处理多个异步请求时。
用法如下(取自https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest)
id_status
答案 3 :(得分:0)
什么在合适的"回调"时尚是定义一个返回这样的承诺的服务!
$http.head("url2check").then(function () {
return true;
}, function () {
return false;
});
在控制器中使用服务:
<service>.<service method>.then(function (found)) {
if (found) {......
}
@jon将其称为异步是正确的!
答案 4 :(得分:0)
XMLHttpRequest回调函数和使用数据数组上传文件
function HttpPost(url, arr, cb, form){
if (form === undefined) { var data = new FormData(); }else{ var data = new FormData(form); }
if (arr !== undefined) {
for (const index in arr) {
data.append(index, arr[index]);
}
}
var hr = new XMLHttpRequest();
hr.onreadystatechange=function(){
if (hr.readyState==4 && hr.status==200){
if( typeof cb === 'function' ){ cb(hr.responseText); }
}
}
hr.upload.onprogress = function(e) {
var done = e.position || e.loaded, total = e.totalSize || e.total;
console.log('xhr.upload progress: ' + done + ' / ' + total + ' = ' + (Math.floor(done/total*1000)/10) + '%');
};
hr.open("POST",url,true);
hr.send(data);
}
// HttpPost callback
function cb_list(res){
console.log(res);
var json = JSON.parse(res);
console.log(json.id + ' ' + json.list);
// loop
for (var objindex in json.list){
console.log(json.list[objindex].id);
}
}
示例:
var data = [];
data["cmd"] = "get-cos";
var form = $('#form')[0];
HttpPost('/api-load', data, cb_list, form);
<form id="form" method="POST" enctype="multipart/form-data">
<input type="file" name="file[]" multiple accept="image/*">
</form>
Http标头内容
hr.setRequestHeader("Content-Type", "application/json");
// data:
var json = {"email": "hey@mail.xx", "password": "101010"}
var data = JSON.stringify(json);
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// data:
var data = "fname=Henry&lname=Ford";