## 异步通知,那我要怎么通知你啊?
[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
- 开始
- 公益
- 更好的使用看云
- 推荐书单
- 优秀资源整理
- 技术文章写作规范
- SublimeText - 编码利器
- PSR-0/PSR-4命名标准
- php的多进程实验分析
- 高级PHP
- 进程
- 信号
- 事件
- IO模型
- 同步、异步
- socket
- Swoole
- PHP扩展
- Composer
- easyswoole
- php多线程
- 守护程序
- 文件锁
- s-socket
- aphp
- 队列&并发
- 队列
- 讲个故事
- 如何最大效率的问题
- 访问式的web服务(一)
- 访问式的web服务(二)
- 请求
- 浏览器访问阻塞问题
- Swoole
- 你必须理解的计算机核心概念 - 码农翻身
- CPU阿甘 - 码农翻身
- 异步通知,那我要怎么通知你啊?
- 实时操作系统
- 深入实时 Linux
- Redis 实现队列
- redis与队列
- 定时-时钟-阻塞
- 计算机的生命
- 多进程/多线程
- 进程通信
- 拜占庭将军问题深入探讨
- JAVA CAS原理深度分析
- 队列的思考
- 走进并发的世界
- 锁
- 事务笔记
- 并发问题带来的后果
- 为什么说乐观锁是安全的
- 内存锁与内存事务 - 刘小兵2014
- 加锁还是不加锁,这是一个问题 - 码农翻身
- 编程世界的那把锁 - 码农翻身
- 如何保证万无一失
- 传统事务与柔性事务
- 大白话搞懂什么是同步/异步/阻塞/非阻塞
- redis实现锁
- 浅谈mysql事务
- PHP异常
- php错误
- 文件加载
- 路由与伪静态
- URL模式之分析
- 字符串处理
- 正则表达式
- 数组合并与+
- 文件上传
- 常用验证与过滤
- 记录
- 趣图
- foreach需要注意的问题
- Discuz!笔记
- 程序设计思维
- 抽象与具体
- 配置
- 关于如何学习的思考
- 编程思维
- 谈编程
- 如何安全的修改对象
- 临时
- 临时笔记
- 透过问题看本质
- 程序后门
- 边界检查
- session
- 安全
- 王垠
- 第三方数据接口
- 验证码问题
- 还是少不了虚拟机
- 程序员如何谈恋爱
- 程序员为什么要一直改BUG,为什么不能一次性把代码写好?
- 碎碎念
- 算法
- 实用代码
- 相对私密与绝对私密
- 学习目标
- 随记
- 编程小知识
- foo
- 落盘
- URL编码的思考
- 字符编码
- Elasticsearch
- TCP-IP协议
- 碎碎念2
- Grafana
- EFK、ELK
- RPC
- 依赖注入
- 开发笔记
- 经纬度格式转换
- php时区问题
- 解决本地开发时调用远程AIP跨域问题
- 后期静态绑定
- 谈tp的跳转提示页面
- 无限分类问题
- 生成微缩图
- MVC名词
- MVC架构
- 也许模块不是唯一的答案
- 哈希算法
- 开发后台
- 软件设计架构
- mysql表字段设计
- 上传表如何设计
- 二开心得
- awesomes-tables
- 安全的代码部署
- 微信开发笔记
- 账户授权相关
- 小程序获取是否关注其公众号
- 支付相关
- 提交订单
- 微信支付笔记
- 支付接口笔记
- 支付中心开发
- 下单与支付
- 支付流程设计
- 订单与支付设计
- 敏感操作验证
- 排序设计
- 代码的运行环境
- 搜索关键字的显示处理
- 接口异步更新ip信息
- 图片处理
- 项目搭建
- 阅读文档的新方式
- mysql_insert_id并发问题思考
- 行锁注意事项
- 细节注意
- 如何处理用户的输入
- 不可见的字符
- 抽奖
- 时间处理
- 应用开发实战
- python 学习记录
- Scrapy 教程
- Playwright 教程
- stealth.min.js
- Selenium 教程
- requests 教程
- pyautogui 教程
- Flask 教程
- PyInstaller 教程
- 蜘蛛
- python 文档相似度验证
- thinkphp5.0数据库与模型的研究
- workerman进程管理
- workerman网络分析
- java学习记录
- docker
- 笔记
- kubernetes
- Kubernetes
- PaddlePaddle
- composer
- oneinstack
- 人工智能 AI
- 京东
- pc_detailpage_wareBusiness
- doc
- 电商网站设计
- iwebshop
- 商品规格分析
- 商品属性分析
- tpshop
- 商品规格分析
- 商品属性分析
- 电商表设计
- 设计记录
- 优惠券
- 生成唯一订单号
- 购物车技术
- 分类与类型
- 微信登录与绑定
- 京东到家库存系统架构设计
- crmeb
- 命名规范
- Nginx https配置
- 关于人工智能
- 从人的思考方式到二叉树
- 架构
- 今日有感
- 文章保存
- 安全背后: 浏览器是如何校验证书的
- 避不开的分布式事务
- devops自动化运维、部署、测试的最后一公里 —— ApiFox 云时代的接口管理工具
- 找到自己今生要做的事
- 自动化生活
- 开源与浆果
- Apifox: API 接口自动化测试指南