-
Notifications
You must be signed in to change notification settings - Fork 272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
从HTML5与PromiseA+规范来看事件循环 #13
Labels
Comments
make 这种问题很纠结人啊。 |
@ipengyo 主要是规范就一套,不同环境自己实现,最后的结果可能都不太一致=。= |
另:《从hello world看JavaScript隐藏的黑魔法制》链接好像错了 |
@xhlwill 已修正 谢谢指出~ |
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
写在最前
本次分享一下从HTML5与PromiseA+规范来迅速理解一波事件循环中的microtask 与macrotask。
欢迎关注我的博客,不定期更新中——
JavaScript小众系列开始更新啦
——何时完结不确定,写多少看我会多少!这是已经更新的地址:
这个系列旨在对一些人们不常用遇到的知识点,以及可能常用到但不曾深入了解的部分做一个重新梳理,虽然可能有些部分看起来没有什么用,因为平时开发真的用不到!但个人认为糟粕也好精华也罢里面全部蕴藏着JS一些偏本质的东西或者说底层规范,如果能适当避开舒适区来看这些小细节,也许对自己也会有些帮助~文章更新在我的博客,欢迎不定期关注。
先来看段代码
从这段代码中我们发现里面有两个定时器
setTimeout
,每个定时器中还嵌套了Promise。我相信熟悉microtask 与macrotask任务队列的童鞋能很快的知晓答案,这个东西给我的感觉就是清者自清。so 结果是什么?
why?
不做解释直接看下规范中怎么说的:
一个浏览器环境下只能有一个事件循环,同时循环中是可以存在多个任务队列的。
同时我们接着看规范中对event-loop执行过程是如何规定的:
其中的task queues,就是之前提到的macrotask,中文可以翻译为宏任务。顾名思义也就是正常的一些回调执行,比如IO,setTimeout等。简单来说当事件循环开始后,会将task queues最先进栈的任务执行,之后移出,进行到第六步,做microtask的检测。发现有microtask的任务那么会依照如下方式执行:
从这段规范可以看出,当执行了一个macrotask后会有一个循环来检查microtask队列中是否还存在任务,如果有就执行。这说明执行了一个macrotask(宏任务)之后,会执行所有注册了的microtask(微任务)。
一起看起来很正常对吧?
那么如果微任务“嵌套”了呢?就像一开始作者给出的那段代码一样,promise调用了很多次.then方法。这种情况文档中有做出规定么?有的。
简单来说如果有“嵌套”的情况,注册的任务都是microtask,那么就会一股脑得全部执行。
小结
通过上面对文档的解读我们可以知道以下几件事:
那么还剩一件事情就是什么任务是macrotask,什么是microtask?
这张图来源一篇翻译PromisA+的文章,里面所提到的关于任务的分类。
但是!我对于setImmediate与process.nextTick的行为持怀疑态度。理由最后说!不过在浏览器运行环境中我们不需要关系上面那两种事件。
测试一下代码
在本文一开始就提出,这段代码要在新版chrome中运行才会得到正确结果。那么不在chrome中呢?
举个例子,别的作者不一一测试了,这是safari中的结果。我们可以看到顺序被打乱了。so为什么我执行了一样的代码结果却不同?
个人认为若出现结果不同的情况是由于不同执行环境(chrome, safari, node .etc)将回调需要执行的任务所划分到的任务队列与PromiseA+规范中所提到的任务队列中的任务划分准则执行不一致导致的。也就是Promise可能被划分到了macrotask中。有兴趣深入了解的童鞋可以看下这篇tasks-microtasks-queues-and-schedules.
抛一个作者也解释不清的问题
细心的童鞋可能发现我一直强调的js运行环境是浏览器下的事件循环情况。那么node中呢?
还是这段代码,打印出来会不会有区别?多打印几次结果一样么?为什么会这样?
我只能理解到node通过libuv实现事件循环的方式与规范没有关系,但具体为什么会打印出不同的效果。。求大神@我
最后
不定时更新中——
有问题欢迎在issues下交流。
The text was updated successfully, but these errors were encountered: