同步, 非阻塞: 调用方发起调用直至得到结果之前这段时间, 可以做其它事情. 但被调函数接收到参数直到运算结束之前, 都不会返回. 很显然这个逻辑概念说得通, 但其实是反常理的. 因为: 如果调用方在发起调用之后, 得到结果(函数返回)之前, 要去做其它事情, 那么就有一个隐含的前提条件: 调用方必须知道本次调用的耗时, 且被调方(函数)严格遵守这个时间约定. 一毫秒不多, 一毫秒不少. 这在代码的世界里是很难达到的.
异步, 且阻塞: 调用方发起调用直至得到结果之前, 都不能干其它事情. 被调用函数接收到参数之后立即返回, 但在随后的某个时间点才把运算结果传递给调用方. 之后调用方继续活动. 这个逻辑概念依然说得通, 但是很别扭. 这就相当于, 在你问淘宝客服问题的时候, 淘宝客服的自动回复机器人已经给你说了"客服很忙哟, 可能过一会才能答复你", 但你就是啥也不干, 非得等到客服答复你之后, 才去上厕所. 这种情景在代码世界里可能发生, 但似乎很智障.
异步, 非阻塞: 调用方发起调用直至得到结果之前这段时间, 可以做其它事情. 被调函数接收到参数后立即返回, 但在之后的某一个时间点才把运算结果传递给调用方. 这说起来很绕口, 举个栗子, 还是客服:
你拿出手机, 向客服发送消息, "在吗?". 然后把手机放桌子上, 转向上厕所去了.
客服收到你的消息, 机器人回复你"不好意思, 客服现在很忙, 但我们会尽快答复你的, 亲!".
你上厕所回来了, 看手机没消息, 又去吃饭了.
客服开始处理你的消息, 终于开始给你真正的回复"亲, 2333号客服为您服务, 你有什么要了解的吗?".
你吃饭的过程中, 手机震动, 你点开淘宝, 发现有了回复. 整个流程结束.
可以看到
阻塞方式下, 调用方总是能第一时间拿到调用结果. 因为在阻塞期间, 调用方啥也不干, 就等着函数返回结果. 非阻塞方式下, 调用方一般都是在函数返回了结果之后才去查看运算结果.
异步方式下, 被调用方可以推迟处理任务. 客服收到你的消息后可以先把饭吃完, 函数收到你的调用后并不一定立即就开始运算.
同步且阻塞, 双方都是杠精, 都是老实人. 理解起来比较自然.
异步非阻塞, 调用方不在乎什么时候能得到运算结果. 被调用方不在乎调用方着急不着急, 双方都是佛系青年. 理解起来也比较自然.
还有一个点要给大家介绍到, 就是回调函数. 在上面讲过, 异步调用, 需要函数以某种机制, 在运算结果得出之后, 将运算结果传递给调用方. 但回调函数又绕了一个弯.
假设没有回调函数机制, 异步流程就是:
顾客询问客服, "你们家有没有红色36D的胸罩啊? 我想给我老婆买一件, 我老婆的胸是36D的". 然后去上厕所去了
自动机器人向顾客回复"很忙哟, 请耐心等待"
客服开始处理顾客的询问. 去库房查货.
库房有货, 客服要想办法将这个信息送到顾客手中. 他通过淘宝客户端发表了答复, 淘宝客户端导致手机震动, 这个震动信号通知了顾客.
顾客在厕所正拉屎, 看到手机上的消息提醒, 思考了一分钟, 顾客下单购买了这个胸罩.
这个流程里顾客做了两件事:
询问客服"有没有36D的红色胸罩". 这是调用函数的行为
在得到肯定的答复之后, 下单购买了这个胸罩. 这是得到函数返回的运算结果, 并根据运算结果进一步执行程序流程.(调用了另外一个函数: 购买)
而淘宝客服只做了一件事:
查询库房里是否有货
而有了回调机制后, 异步流程就是这样的:
顾客询问客服, "你们家有没有红色36D的胸罩?". 然后顾客把手机交给秘书, 叮嘱道:"你盯着这个客服, 如果她说有, 你就下单买了, 地址写我家, 如果没有, 你就啥也不做". 然后顾客坐上了出差的飞机
自动机器人向顾客回复"很忙哟, 请耐心等待"
客服开始处理顾客的询问. 去库房查货.
库房有货, 客服要想办法将这个信息送到顾客手中. 他通过淘宝客户端发表了答复, 淘宝客户端导致手机震动, 这个震动信号通知了秘书.
秘书根据老板的指示, 下单购买了这个胸罩.
这个流程里, 顾客做了两件事:
询问客服"有没有36D的胸罩". 这是调用函数行为.
向秘书叮嘱. 这是向消息监控方注册回调函数的行为. 消息监控方负责接收函数的返回结果. 回调函数则是: "如果有, 就买给老板夫人, 如果没有, 就什么也不做"
淘宝客服只做了一件事:
查询库房里是否有货
而消息监控方, 也就是秘书, 做了一件事:
根据客服的答复选择不同的行为. 即在函数调用结果得出之后, 调用回调函数.