1.回调的故事
1.最近辞职换了新工作,新公司的工作模式是前后端分离的,但是目前前端框架还需要了解以及熟悉,之前的框架又想废弃,于是不得不用原生来开发,但是原生得造*啊,于是只能用js的类库jQuery框架来进行开发,然后jq中ajax方法是用的最多的方法。
之前写ajax一直是这样:
$.ajax({
url : "/xxxx",//请求的链接
type : "get",
data : {},
success : function(data){
//执行业务逻辑
},
});
所有的业务逻辑代码都放在success里面,然后就发现经常得开几个不同的$.ajax()方法实现几乎相似的方法,导致sucess方法里面业务逻辑非常混乱,并且整个代码的复用率并不高。
2.于是就想着封装ajax方法,ajax方法仅仅只是用来获取数据而不做其他层次的事情,这样就可以在拿到数据后对数据写自己的业务逻辑代码了,而不会导致业务逻辑代码混乱。于是我们就改装成这样的函数:
function getData(arg){
var returnData,
url = arg.url,
type = arg.type,
data = arg.sendData || {};
var contentType = arg.contentType || "application/x-www-form-urlencoded";
$.ajax({
url : url,
type : type,
data : JSON.stringify(data),
contentType : contentType,
async: false,
dataType : "json",
success : function(data2){
returnData = data2;
},
});
return returnData;
}
定义一个局部变量returnData来接受success返回的数据,并且由于ajax默认是异步的,需要给改成同步的,这样returnData才能获取到数据,但是渐渐发现同步会阻塞接下来业务逻辑的执行,如果网速过慢的话会导致接下来代码都无法执行,这不是我所需要的获取数据的方法。于是就又想着改进这个方法。
3.之前看过jQuery源码,ajax方法里传入参数,其中参数包括一个函数叫success,但是success是把整个函数代码传入ajax方法里的,然后在后台返回数据到前端时进行调用:
var success = data.success;//data是ajax进行调用时传入的参数
if(xhr.readyState==4 && xhr.status==200){
success(data);//这儿进行调用
}
我就想着照葫芦画瓢来用回调来获取得到的数据,这样就可以又不会阻塞其他业务逻辑的进行,又可以在数据获取到之后执行我想做的逻辑,于是就给改成:
function getData(arg){
var url = arg.url,
type = arg.type,
data = arg.sendData || {},
returnData = arg.returnData || function(){};//如果returnData为underfind时设置函数为空
var contentType = arg.contentType || "application/x-www-form-urlencoded";
$.ajax({
url : url,
type : type,
data : JSON.stringify(data),
contentType : contentType,
dataType : "json",
success : function(data2){
returnData(data2);//这儿运行函数
},
});
}
//调用获取数据的函数
getData({
url : "/isleep/doctor",
type : "post",
sendData : {"doctor_id" : doctorId,"record_id" : recordId},
contentType : "application/json",
returnData : showData, //传入的回调函数
});
//设置回调函数
var showData = function(data){
//业务逻辑代码
}
1.先设置一个获取数据的函数,函数传入一个参数,参数是一个对象,跟ajax差不多,其中包括url等参数。
2.调用getData函数,传入url等参数,在returnData是直接把showData代码作为参数传入到getData函数里面去的,这样在getData里returnData就是一个函数了,指针指向showData,即把showData赋值给returnData。
3.这时当success执行后,就会执行success函数里面定义的returnData函数,而returnData执行即相当于执行showData函数。
这样我们就可以拿到后台返回的数据,在showData里面定义我们自己想要的业务逻辑,而不去管怎么获取数据,以及ajax同步会阻塞进程的情况了。
2.回调的解释
百度百科是这样解释的:
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
大体意思就是回调是通过函数定义的变量通过参数传入另一个函数,在另一个函数进行调用,我们就称之为回调函数。
而回调字面解释意思就是回头去调用,以上面为例,当getData进行到success函数时,会调用returnData(data)函数,但ajax方法里面为定义,根据函数作用于链会向上找,即找到定义returnData的地方,而returnData是只是通过参数赋值的,传进来的只是一个指针(地址),再根据地址去找到最上层的showData函数,在success里面传入data参数,并调用。而js引擎在解释js时,js引擎会首先初始化函数,即getData是早就定义好的,但一直没有进行调用,直到进行到success时才进行调用,所以先定义好,再调用我们称之为回调。
3.回调的意义
回调作为javascript最重要的一个特性,那么他的意义何在呢?当我们想封装类库并且提供接口时,我们发现这个接口每个人都有可能有自己的业务逻辑,我们不能把这个接口给写死,这是提供一个回调函数不得不说是一个更棒的办法,我们把回调函数的参数定义好,告诉用户有可能会有哪几个参数,然后用户拿这个参数去定义自己的业务员逻辑,这样就可以构成一个完成的函数体了。
这样写接口就可以专注于写接口而不会去考虑会发生的业务员逻辑情况,而用户拿到接口就可以根据接口提供的数据来自定义业务逻辑了。