ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 异步通知,那我要怎么通知你啊? [Java帝国之拨云见日识回调 - 码农翻身](http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513481&idx=1&sn=e1ebb1389eda4a36328ce6e8ad833b2f&chksm=80d67a4ab7a1f35c5218f2c62cd59e539d6053cfc81a3afc33b300d9cd3b70bba661ea9cb851&scene=21#wechat_redirect) >[danger] 他拎了两瓶好酒去找FileIO商量: “兄弟, 我听说有一种异步保存的办法, 你那边能不能用下? 保存数据的时候起一个线程, 把主线程让回给我,保存好了再通知我,我也不用老是等你,是吧?” FIleIO想了想说:“这样确实可以解决问题,但每天找我保存数据的人也很多,**而且我也不知道在完成数据的写入之后怎么通知你呢?**” 小张把两瓶好酒往前一推, “我们关系这么好,你再开个专属我的方法呗,**我在调用你的saveStrToFile方法的时候顺便把我的实例给你**,你搞完之后通过我的实例调用我的方法通知我就行啦。就调我的onResult()这个方法吧。这事要保密, 天知地知你知我知就行了”。 怎么通知,我调用你的时候就可以跟你说好啊。 我让你做一件事情,但是你做得很慢,并不能够立马返回给我结果,害我一直在那儿等着你给我返回结果,什么都做不了,我又是个急性子,真是郁闷。 程序是自上而下顺序执行的,很多时候后一步的操作依赖于前一步操作的返回结果,所以必须按照顺序依次执行,因为我们的代码就是这么写的。 如果我不想等,那我就需要把操作拆分解耦,解耦我可以做到,就是让后面的操作不一定非要等到前面操作的完成,不是非要依赖于前面的返回结果,也就是我不用等你了。把耗时的操作,对整体结构非关键部分的操作异步执行。 好想法。 可是异步执行完,你要通知我,对我说你帮我做好了啊。 我为什么要你通知我你做好了呢,换句话说,我为什么要知道异步的事情做好了呢? 因为,事情做好了,不管什么结果,我还要接着处理一下啊,不是说异步我丢给你了我就不管了,我只是暂时没空等你,我希望你给我开个后门,在背后帮我完成,做好了你还是要跟我说的,然后我还要继续处理的。 可是问题是,我做好了怎么通知你呢,并且到时候你还在不在我都不知道? 转换一下思路:一切是为了解决问题的,而不在于解决问题的方式。 你想让我做好后通知你,不就是你还想处理一下我的执行结果吗?既然这样,你让我做事的时候,直接把你本来想要处理的过程实例也一并跟我说了不就好了吗,这样到时候我做完了就知道帮你处理的,不然到时候我还不知道要怎么找你呢,也不知道那个时候你还在不在线。你说这样可以吗? 是啊,我怎么没想到呢,哈哈,你真聪明,我太笨了。那我需要给你传两个参数哈,一个是需要你帮我处理异步任务,一个是完成后的处理实例,这样到时候你就可以帮我处理了,我也不用在什么地方等着你来通知我了,哈哈。 你不用担心到时候怎么找我,我也不用在什么地方一直等你通知我。真好。 解决问题的本质是要认清楚问题的本质,有时候固有思维容易影响我们,所以要跳出固有的思维方式,用最直接的方式解决问题是最有效的方式。 * * * * * 上面有一个问题没说,我怎么做到把 我要你帮我做的任务发给你? web不支持这种方式,所以这时候需要请出队列了。 > 其实这个AJAX是一样的,在进行异步请求的时候就把回调的匿名函数当做参数传给它了,在等待服务端返回的过程中并不会紫塞主线程,这是一个异步的操作,响应完成后它就会自己调用之前传递给它的匿名函数。其实ajax就像是一个运行在客户端的客户端软件一样,它支持这种模式,原理是因为客户端在主线程之外还有一个事件循环的机制,但是web服务端,B/S这种架构的软件并不支持这种模式,一个请求处理完成后必须立即返回给客户端,客户端才能够收到http响应,才算完成一次请求,并且http是无状态的,服务端不能够和客户端进行主动通信,这不是web服务能力的问题,而是由web服务的本质所决定的,所以这种异步,回调的方式想要用在服务端就要换一种方式了,那就是队列。 [Java 帝国之消息队列](http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513507&idx=1&sn=d6db79c1ae03ba9260fb0fb77727bb54&chksm=80d67a60b7a1f376e7ad1e2c3276e8b565f045b1c7e21ef90926f69d99f969557737eb5d8128&scene=21#wechat_redirect) > 晚上到家,小张苦思悯想: 原来订单系统和库存系统都在一个虚拟机中, 处理起来很方便, 但是现在是个远程的Web服务, 酒鬼小李不给我返回结果, 我就没法结束, 这是典型的同步操作, 能不能改成异步的呢? 我把一个订单包裹发给小李, 他什么时候处理我就不用管了, 这样我这边的效率就会大大的提高! 可是现在的Web服务并不支持这种方式, 我怎么才能把包裹发过去呢? * * * * * [小李的数据库之旅(上)](http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513312&idx=1&sn=f0c3e5623cc1042fa486c91c5d0ec6d4&scene=21#wechat_redirect) >[danger] “所有计算机的问题都可以通过增加一个中间层来解决” * * * * * ### 思考 web服务中,客户端一次请求后,服务端应该立马返回并断开,越快越好,这样用户就会感觉很快,PHP有ob_flush ,其实也可以在不断开,一直往浏览器推送数据,但是这样的体验并不好,因为用户如果感觉浏览器加载的圈圈一直在转的话,他会觉得这个网站打开好慢,因为在所有人的主观意识中,网站应该就是建立请求后,响应完成后应该就立马断开,这样才体现网站访问速度很快。并且如果你想用AJAX和ob_flush来配合做,其实也不现实,[它对ajax是无效的](http://blog.csdn.net/u011832039/article/details/51387548),因为ajax是要在服务端响应完成后才执行的,所以服务端软件和客户端软件有很大的本质区别,不想客户端软件,进程在本地,异步使用起来就很方便,在服务端就要转变一些思路,换一种方式了。 ### 参考: [定时-时钟-阻塞 · php笔记 · 看云](https://www.kancloud.cn/xiak/php-node/400090) [多进程/多线程 · php笔记 · 看云](https://www.kancloud.cn/xiak/php-node/419460) [nginx、swoole高并发原理初探 - 畅想代码 - SegmentFault](https://segmentfault.com/a/1190000007614502?utm_source=coffeephp.com) [javascript - 究竟能不能用死循环?或者其实我们就活在一个死循环的世界中? - SegmentFault](https://segmentfault.com/q/1010000009586182) [php与ajax交互——实现php实时返回结果给ajax,并在后台保持继续运行的方法](http://blog.csdn.net/u011832039/article/details/51387548) [Nginx+Php-fpm运行原理详解](http://blog.csdn.net/u013474436/article/details/52972699) [异步编程那些事 - 颜海镜](http://yanhaijing.com/javascript/2017/08/02/talk-async/) [怎样理解阻塞非阻塞与同步异步的区别?-IT老友的回答-悟空问答](https://www.wukong.com/answer/6492953923190522125/?iid=12619555732&app=news_article&share_ansid=6492953923190522125&wxshare_count=1&tt_from=weixin&utm_source=weixin&utm_medium=toutiao_android&utm_campaign=client_share) [hprose真的让PHP实现异步了吗?-悟空问答](https://www.wukong.com/question/6482944667104051469/?wxshare_count=1&tt_from=weixin&utm_source=weixin&utm_medium=topic_android&utm_campaign=client_share) [异步与回调的设计哲学 - 掘金](https://juejin.im/post/58b599aa44d9040068628fb6) [Node.js : 我只需要一个店小二 - 码农翻身](https://mp.weixin.qq.com/s/BzrAacmJZEFRXE3vijCVQQ) ~~~ 我的提问: 老大你好,我有个问题,node是通过事件回调来实现异步的,就跟前端写js一样的方式,但是在服务端这明显的有问题啊,你那个 送客()也是在回调里面的,也就是说不能够立即返回给前端,只有服务端完全响应完,浏览器才能收到200的状态啊,不然网页不一直处于加载状态吗?这样ajax也得不到响应完成的状态,那这些前台还是需要等,这样不一点意义都没有啊,好纠结,在线等回复。我感觉web访问式服务,要想实现异步处理任务的效果只能用队列吧,你文中的效果其实跟浏览器端的js一样,这种事件循环适应于客户端软件,这在B/S中行不通,不知道我的理解对不对。 回复: 待回复 ~~~ #### 思考: 其实,我说的都是对的,只是理解上出了偏差,node异步是指在服务端,node本身是单进程的,不像php Nginx那种运行方式,所以为了提升并发服务能力,node必须的很好的支持异步操作,这个异步是指node单进程处理大量的访问而需要进行异步处理,而不是针对于我问题中的情况,问题中的情况没错,都是对的,是只能使用队列,才能让服务端尽快返回,耗时的任务放到队列才能是前端尽快得到响应,从而无需等待。 是我理解错了node异步的意思,这里异步指的是处理请求和io的方式。比如php 30和个php-fpm进程,来30个请求,都是读大文件的,那么第31个请求就暂时进不来了,而node只需要一个进程,也可以让第31个人进来,第一个人读文件异步读,不影响第二个人更新资料,这就是node异步的体现。而不是我理解的在一个请求中,先把准备好的内容[先推送到浏览器](http://www.laruence.com/2011/02/13/1870.html),而后面脚本则继续执行,这样可以让浏览器提前得到响应,或者与[nginx连接断开](http://www.laruence.com/2011/04/13/1991.html),但当前php-fpm脚本不会结束,而是继续执行耗时任务,异步根本不是这样理解的,这种方式不叫异步,和异步没关系,只是一种奇淫巧技而已,并没有从根本上解决问题。 * * * * * **将php与node这样对比,本身就错了,它们根本不是一个东西,不能这样比较,一个php是web服务器中一个独立的单元,而node.js脚本则可以代表整个web服务器,所以这两者根本就没有可比性。所以我这个问题真是愚蠢,根本就没有弄清楚它们是什么嘛。** PHP代码是线性从上到下按顺序执行的(可以预测代码的执行顺序),没有事件的概念,所以效率很低,而node.js就不同了,JS天生的异步,所以某些情况下,性能会比PHP好。 >[danger] **node.js = Nginx + php** * * * * * > PHP 页面没有任何事件的概念,只有两个事件也许有意义并且有用处,(1)URL调用事件,(2)URL调用完成事件。URL调用事件是通过运行PHP脚本处理,重点是,整个PHP脚本就是URL调用处理。当PHP脚本执行完成,生成了所有输出,可以被看做是URL调用完成事件。为了处理这种事件,需要在PHP页面末尾加上其他处理代码。所以PHP页面是可以看做是两个事件之间的一大段无事件代码,就像三明治一样。 > > 基本上PHP在做一件事情的时候需要等到其他事情的完成,这种方式效率非常低(让计算机资源闲置了,没有得到充分利用)。在PHP中如果有一些任务需要耗费太长时间,你只能一直等待该任务完成,没有其他更快的向下执行的方式。 **回调函数:** 回调函数是一种电泳代码时,将自己的代码插入到被调用的函数的方法。它是在不修改函数本身代码的情况下改变函数的行为的方法。 **事件与回调:** 一个事件可以跟回调函数联系到一起,这也被叫做事件处理程序。事件处理程序会在一个事件发生时被执行。on()函数可以将一个事件和事件处理函数联系到一起。 (摘自:《写给PHP开发者的Node.js学习指南》) * * * * * [驳PHP优于Node.js的五大理由 - CNode技术社区](https://cnodejs.org/topic/51659db96d38277306d202a3) > 回调真的恶心吗?当你真的理解事件驱动的时候,你会发现回归才是编程的本质,一切的结束都是回归,而不是强求! [Node.js和PHP运行机制对比 - NT.Wang - 博客园](https://www.cnblogs.com/NTWang/p/6271696.html) > 谁的效率更高,通常情况下是这样认为的,那就是,谁没有让cpu闲着,谁能最大限度的压榨cpu资源,充分利用计算机的效能,谁的效率性能就更高。 [\[翻译\]了解 NodeJS 看这一篇就够了](http://mp.weixin.qq.com/s/QRsX6D6i00V5Vyh9k5fchw) [异步编程需要“意识”](http://mp.weixin.qq.com/s/Pd4RDvjItxIf17EMetNz4Q) [Node 定时器详解](https://mp.weixin.qq.com/s/FZefHsoVqtkcjUJK3KwRFw) last update:2018-2-12 01:22:07