什么是回调函数callback?
需求
A,B两个小组开发一个功能。B小组开发制作油条模块:make_youtiao。A小组需要调用B小组开发的模块,然后执行后续的操作:sell()如下图:
上面的方式A小组必须等待B小组开发的模块make_youtiao执行完成后才能执行sell()。
上图代码的写法:
1 | make_youtiao(10000); |
存在的问题:A小组不知道啥时候B小组执行完,因此必须等待B小组执行完,再执行后续的操作sell(),效率不够高。
要是A能够告诉B小组,你执行完make_youtiao后自动执行sell()就好了!我把任务交给你之后就去做其他事情啦~
看懂了?回调函数就是上面的sell()函数,不过他要作为参数传递给B小组。
上面功能用回调函数实现
B小组开发的模块这样定义:
1 | void make_youtiao(int num, func call_back) { |
A小组这样调用,将make_youtiao完成后和make_youtiao相关的工作sell作为参数传入:
1 | make_youtiao(10000, sell); |
新的编程思维模式
同步的思维方式:
1 | res = request(); |
这种是必须等待执行完,拿到结果res,我们才能处理下一步和结果相关的工作handle()。
异步的思维方式:
1 | request(handle); |
这种方式不关心request何时执行完,将后续的工作handle传入request,当request执行完了,自动就把handle处理了。
举个例子说明同步和异步的区别:
同步:老板凡事亲力亲为,自己亲自拨电话等待电话接通(request)。然后吩咐事情(handle)。
异步:老板直接告诉小秘吩咐的事情是什么,小秘去完成这些琐事。老板就可以腾出手来完成一个亿的小目标啦~
正式定义
在计算机科学中,回调函数是指一段以参数的形式传递给其它代码的可执行代码。可以理解为一种设计思想。
一般函数:我们自己编写的函数在自己内部调用,实现方是我们自己,调用方是我们自己。
回调函数:实现方是我们自己,将函数传给第三方,由三方库来调用。实现方是我们自己,调用方是第三方库。
进一步思考为什么需要callback?
我们之所以要传给第三方库自己定义的函数,是因为第三方库自己的代码执行完成之后,并不知道接下来应该做什么,因此对外提供了一个回调函数(跟对外提供一个接口有点类似,由调用方来具体实现)
最后补充一点是:回调函数被调用的时间点,是需要有特定的事件(event)发生后,才能执行回调函数。比如油条制作完成,文件读取完成,接收到消息。因此回调函数本质上是一个event_handler。