初学js的时候,被回调函数搞得很晕,现在回过头来总结一下什么是回调函数。
我们先来看看回调的英文定义:A callback is a function that is passed as an argument to another function and is executed after its parent function has completed。
字面上的理解,回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。
其实也很好理解对吧,回调,回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数。但是以前看过很多博客,他们总是将回调函数解释的云里雾里,很高深的样子。
举一个别人举过的例子:约会结束后你送你女朋友回家,离别时,你肯定会说:“到家了给我发条信息,我很担心你。” 对不,然后你女朋友回家以后还真给你发了条信息。小伙子,你有戏了。其实这就是一个回调的过程。你留了个参数函数(要求女朋友给你发条信息)给你女朋友,然后你女朋友回家,回家的动作是主函数。她必须先回到家以后,主函数执行完了,再执行传进去的函数,然后你就收到一条信息了。
现在基本理解回调函数的意思了吧。不理解的话没关系,我们用代码说话。
//定义主函数,回调函数作为参数 function A(callback) { callback(); console.log('我是主函数'); } //定义回调函数 function B(){ setTimeout("console.log('我是回调函数')", 3000);//模仿耗时操作 } //调用主函数,将函数B传进去 A(B); //输出结果 我是主函数 我是回调函数
上面的代码中,我们先定义了主函数和回调函数,然后再去调用主函数,将回调函数传进去。
定义主函数的时候,我们让代码先去执行callback()回调函数,但输出结果却是后输出回调函数的内容。这就说明了主函数不用等待回调函数执行完,可以接着执行自己的代码。所以一般回调函数都用在耗时操作上面。
一. 回调函数的作用
js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作(异步AJAX,文件加载,动态加载html等),这时候就需要用到回调函数,否则会找不到对象(附值,函数未加载完成)。
二. 回调函数的解释
因为函数实际上是一种对象,它可以存储在变量中,通过参数传递给另一个函数,在函数内部创建,从函数中返回结果值”,因为函数是内置对象,我们可以将它作为参数传递给另一个函数,到函数中执行,甚至执行后将它返回,它一直被“专业的程序员”看作是一种难懂的技术。
回调函数是一个作为变量传递给另外一个函数的函数,它在主体函数执行完之后执行。
比如:
function A有一个参数function B,function B会在function A执行完成之后被调用执行。
三. 回调函数的使用方法
代码如下:
function a(callbackFunction){ alert("这是parent函数a"); var m =1; var n=3; return callbackFunction(m,n); } function b(m,n){ alert("这是回调函数B"); return m+n; } $(function(){ var result = a(b); alert("result = "+ result); });
执行顺序为:
这是parent函数a
这是回调函数B
result = 4
函数首先执行了主题函数a,之后调用了回调函数b,最后返回函数a的返回值。
附高级用例:
示例:
//点击 查看用户详细 var queryDetailUser = function(){var userId = Number(5); var one; query(userId, function(data) {//步骤1:调用query方法 one = data; $('body').empty().load('load/DetailUser.jsp',function(){ var template = '<tr>'+ '<td>sex</td>'+ '<td>birthday</td>'+ '</tr>'; var tr = template.replace('sex',one.sex).replace('birthday',one.birthday); $('tbody').empty().append(tr); }); }); } //查单个实体 var query = function(userId,fn){ var param = { userId : userId }; $.ajax({ type : "GET", url : 'xxx', contentType : "application/json; charset=utf-8", data : param, dataType : "json", success : function(result) { fn(result);//步骤2:调用传进来的函数(把已取到的数据传进去) } }); }
详细版:
//绑定-日期提交 $('#year_and_mouth_by_one').click(function(){ var yearAndMouthStartByOne=$('#datetimeOneDay').datebox('getValue'); if (yearAndMouthStartByOne=='') { alert('轻选择日期!'); return; } //1.请求数据,2.回调更新视图 request(yearAndMouthStartByOne,model.updateOneDay); }); //1.请求数据,2.回调更新视图 var request = function (yearAndMouthStartByOne,fn) { var param = { pageNum : 1, pageSize : 100, yearAndMouthStartByOne:yearAndMouthStartByOne }; $.ajax({ type : "GET", beforeSend: function(request) { request.setRequestHeader("adm", $("#adm").val()); }, url : PathList.adminQueryAccessLogForDay, data : param, success : function(result) { //替换模型 model.result=result; //保存日期选择, 分页组件取中日期按天 model.yearAndMouthStartByOne=yearAndMouthStartByOne; //console.log(model.yearAndMouthStartByOne); //更新视图层 fn(); //激活分页组件(传入请求url, 更新视图方法名) model.fenyedView(PathList.adminQueryAccessLogForDay, model.updateOneDay); } }); } //更新视图 model.updateOneDay = function() { //console.log(data); $('#flag1').empty().load('load/rquest_by_one.jsp',function(){ $('#tbo2').empty(); var template = '<tr>'+ '<td>userId</td>'+ '<td>userName</td>'+ '<td>lastTime</td>'+ '<td>lastUrl</td>'+ '<td>ipCount</td>'+ '<td>ipAddress</td>'+ '</tr>'; for (var i = 0; i < model.result.list.length; i++) { var aData = model.result.list[i]; // if (data.userId == '0') { // data.userId = '##'; // } var tr = $(template.replace('userId', aData.userId) .replace('userName', aData.userName) .replace('lastTime', getMyDate(aData.lastTime)) .replace('lastUrl', aData.lastUrl) .replace('ipCount', aData.ipCount) .replace('ipAddress', aData.ipAddress)); tr.data('index', i); $('#tbo2').append(tr); }; }); }