首页   注册   登录
 shawncheung 最近的时间轴更新

shawncheung

V2EX 第 252282 号会员,加入于 2017-09-04 09:28:51 +08:00
今日活跃度排名 8882
shawncheung 最近回复了
@dcatfly 是的,理论上应该是一样的,但是实际结果我手动编译的两个版本与本地安装的版本输出结果不同,个人猜测是使用 libuv 的版本不同,或者其他底层库的原因导致了,我最后通过修改 libuv 源码看到 fs 的回调在 io_poll 阶段执行之后就没有深究了,因为觉得纠结的价值不是很大,如果有兴趣的话你也可以试试手动编译或者使用 async_hook 这个模块来追踪一下。
@nikolausliu 是的,基本是这样的,但是最后有一点就是如果没有定时器也没有 setImmediate 的话,系统是有一个最大等待时间的,而不会一直阻塞。
@nikolausliu 不好意思,回复晚了。
说实话,我一开始看到你的问题也有点愣,我在我的电脑 (macbook pro / node v10.8.0) 上运行是和你得到的结果一致。如何解释这个问题我觉得需要深入到 libuv 的源码才能解释清楚,所以我手动编译了两个版本的 node,一个是 11.0.0, 一个是 10.8.0, 发现手动编译的 node 执行是符合像上面文章的 IO 处理中所说的:
(v2 貌似贴不了图,我复制一下输出结果):
$ ./node example.js
process: 9925.402ms
timer
io
setImmediate

example.js 的内容就是你提供的脚本的内容,而且我也通过修改 libuv 底层代码,打印出来看执行顺序,输出结果如下:手动编译使用的 libuv 版本是 1.23.2



===== EVENT LOOP ROUND 1 =====


[uv__update_time]: execute


[uv__run_timers]: before execute


[uv__run_timers]: after execute


[uv__run_pending]: before execute


[uv__run_pending]: after execute


[uv__run_idle]: before execute


[uv__run_idle]: after execute


[uv__run_prepare]: before execute


[uv__run_prepare]: after execute


[uv__io_poll]: before execute


timeout -1
process: 9986.677ms


===== EVENT LOOP ROUND 2 =====


[uv__update_time]: execute


[uv__run_timers]: before execute
timer


[uv__run_timers]: after execute


[uv__run_pending]: before execute


[uv__run_pending]: after execute


[uv__run_idle]: before execute


[uv__run_idle]: after execute


[uv__run_prepare]: before execute


[uv__run_prepare]: after execute


[uv__io_poll]: before execute


timeout 0
io


[uv__io_poll]: after execute


[uv__run_check]: before execute
setImmediate


[uv__run_check]: after execute


===== EVENT LOOP ROUND 3 =====


[uv__update_time]: execute


[uv__run_timers]: before execute


[uv__run_timers]: after execute


[uv__run_pending]: before execute


[uv__run_pending]: after execute


[uv__run_idle]: before execute


[uv__run_idle]: after execute


[uv__run_prepare]: before execute


[uv__run_prepare]: after execute


[uv__io_poll]: before execute


timeout 0


[uv__io_poll]: after execute


[uv__run_check]: before execute


[uv__run_check]: after execute


[uv__io_poll]: after execute


[uv__run_check]: before execute


[uv__run_check]: after execute


可以确定的是 fs 的 API 调用是在 io_poll 阶段执行的,而且我手动编译的 node 输出结果完全符合文章所说,至于在我本机通过 homebrew 或者其他方式安装的 node 的执行结果不相同,我个人的猜测是安装的 node 底层使用的 libuv 的版本不一致而对 fs 模块的调用进行了某些优化或者其他操作,导致 fs 的回调与 setImmediate 的回调不在同一个事件循环中被处理,结果展示就是 setImmediate 的输出结果比 io 要早。

个人觉得其实不必太纠结这个执行顺序,因为如果在同一个事件循环中处理所有的回调的话会是像文章中所期待的,而我们在实际编码中也不会依赖于异步回调的执行时机来编写业务逻辑。

希望能够对你有帮助
51 天前
回复了 shawncheung 创建的主题 Node.js Promise 杂谈
@Sparetire 已添加,感谢提醒
51 天前
回复了 shawncheung 创建的主题 Node.js Promise 杂谈
@azh7138m 我在文章中有注明副作用的意思:函数副作用指调用函数时除了返回函数值还会修改函数外的变量 https://zh.wikipedia.org/wiki/%E5%87%BD%E6%95%B0%E5%89%AF%E4%BD%9C%E7%94%A8
(在文章中第一个例子就说明了这个问题,也就是通过一个外部变量来控制调用次数,而这个变量是其他代码逻辑无需关心的)
我在文章中说明了 callback 的一些在编码中的危害,而这部分在 you don't know 中也有提及,很多模型设计都是基于 callback 的,而不同模型的特点就在于它们用于解决什么问题,thenable 或者说 Promise 是用于解决回调中调用时机,调用次数的种种问题的。

文章中的意思并不是使用 callback 需要关心函数内部是同步或者是异步的,而是希望通过 Promise 这个机制来尽可能写出易于掌控的代码。而对于 callback 的调用时机不确定是同步还是异步或者是都有可能的情况下,会引发 release zalgo 问题,而这个问题是 API 设计哲学,也就是设计 API 要么完全同步,要么完全异步,详细可以看 https://blog.izs.me/2013/08/designing-apis-for-asynchrony 或者 https://oren.github.io/blog/zalgo.html

不知道以上能不能解决你的疑问
2017-10-18 11:42:57 +08:00
回复了 shawncheung 创建的主题 职场话题 网易和欢聚时代的前端 offer 选择问题?
@zindex 非常感谢!! 回答非常详细,解决了我的很多疑问,相信有数是一个优秀的团队
2017-10-18 11:32:26 +08:00
回复了 shawncheung 创建的主题 职场话题 网易和欢聚时代的前端 offer 选择问题?
@mb4555 抱歉不太了解
2017-10-17 22:05:52 +08:00
回复了 shawncheung 创建的主题 职场话题 网易和欢聚时代的前端 offer 选择问题?
@nim 你的意思是网易有数加班重吗?
关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   816 人在线   最高记录 4385   ·  
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.3 · 14ms · UTC 21:20 · PVG 05:20 · LAX 14:20 · JFK 17:20
♥ Do have faith in what you're doing.
沪ICP备16043287号-1