异步篇: 回调

一. 为什么采用回调?

采用 Ajax 请求为例:

var data = ajax("http://xxx.xx.xx"); // 假设发送一个Ajax请求获取一些数据
console.log(data); // 通常是获取不到data的
  • 因为 Ajax 请求一般是异步的,发送了请求之后,不会等待服务器响应结果而会继续执行后面的代码,而此时 console.log 中的 data 尚未获取到值。
  • 如果采用同步 Ajax 请求,则会阻塞浏览器 I/O ,浏览器操作都会卡滞(如刷新,跳转),体验不好。

为了避免这种情况,所以要等到特定的条件完成,然后再执行特定的程序,而采用回调。

二. 嵌套回调(回调地狱)与链式回调

回调函数的缺陷之一,代码混乱,不好阅读识别。

  • 当回调函数里面调用回调函数,这样一层一层的嵌套下去,通常称为回调地狱。例:
element.onclick = function handler(e){
	setTimeout(function request(){
		ajax("http://xxx.xxx.xx",function res(data){
			if(data == "Data"){
				handler();
			}
			else if(data == "noData"){
				res();
			}
		})
	},2000)
}
"等待元素点击事件触发,然后等待定时器启动,然后等待Ajax请求返回结果,之后可能又从头开始"
  • 现在换一种编写方式实现上面的功能,链式调用。例:
element.onclick = function(){
	handler();
}
function handler(){
	setTimeout(request,2000);
}
function request(){
	ajax("http://xxx.xxx.xx",res);
}
res(){
	if(data == "Data"){
		handler();
	}
	else if(data == "noData"){
		res();
	}	
}

这两种回调的编写方式都有着共同的缺陷,那就是代码可读性不好,程序执行顺序不好追踪,如果说上面的代码好还看出来,实际开发中,代码里面还有会有其他程序调用,会对代码阅读追踪造成更大的困扰。

三. 回调的信任问题

回调函数有时会把自己执行一部分程序的控制权交给第三方,称为控制反转。例:

a();
ajax("http://xxx.xxx.xx",function(){
	c();
})
b();
  • a() 和 b() 的执行都在自身主程序的控制之下, c() 会在 Ajax 请求完成后触发,而 Ajax 何时请求完成,是由第三方控制的。
  • 还有是这种模式一般不会出问题,但是有风险。如果 c() 里面的代码不是自己写的,而是第三方库里面的或同事写的,你期望Ajax请求之后 c() 里面某个功能调用一次,但实际有可能被返回的代码调用多次而发生不期望的结果。

简略的说,回调函数可能会出现以下情况:

  1. 调用回调过早 。
  2. 调用回调过晚(或不被调用)。
  3. 调用回调次数过少或过多 。
  4. 未能传递所需的环境和参数 。
  5. 吞掉可能出现的错误和异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值