js 深入学习 -异步与性能
js 深入学习 -异步与性能
You-Dont-Know-JS(你不知道的 js 这本书的开源版本)
You-Dont-Know-JS(你不知道的 js 这本书的开源版本)
github 国内翻译
https://github.com/JoeHetfield/You-Dont-Know-JS
掘金中文
https://juejin.cn/post/6844903478813261831
github 原帖
简述
一个 JavaScript 程序总是被打断为两个或更多的代码块儿,第一个代码块儿 现在 运行,下一个代码块儿 稍后 运行,来响应一个事件。虽然程序是一块儿一块儿地被执行的,但它们都共享相同的程序作用域和状态,所以对状态的每次修改都是在前一个状态之上的。
不论何时有事件要运行,事件轮询 将运行至队列为空。事件轮询的每次迭代称为一个“tick”。用户交互,IO,和定时器会将事件在事件队列中排队。
Jobs
工作队列,就是插入到这次事件循环的末尾。
jobs 就是 promise 的雏形。 说白了就是 微任务,同步任务执行完了,才执行 微任务。
而 setTimeout 等属于 宏任务, 是下一次事件循环才执行,也就是最后执行。
协作
就是处理千万级,大量的数据的时候,一个执行栈会耗费数秒,甚至上分钟时,导致用户 ui 都卡顿的时候。
我们可以将其拆分为多个 异步执行栈,让他分流执行。 setTimeout(fn, 0) 是最佳实践, 我们使用setTimeout(..0)(黑科技)来异步排程,基本上它的意思是“将这个函数贴在事件轮询队列的末尾”。
注意: 从技术上讲,setTimeout(..0)没有直接将一条记录插入事件轮询队列。计时器将会在下一个运行机会将事件插入。比如,两个连续的setTimeout(..0)调用不会严格保证以调用的顺序被处理,所以我们可能看到各种时间偏移的情况,使这样的事件的顺序是不可预知的。在 Node.js 中,一个相似的方式是process.nextTick(..)。不管那将会有多方便(而且通常性能更好),(还)没有一个直接的方法可以横跨所有环境来保证异步事件顺序。
例如:
1 |
|
如果“http://some.url.1“首先返回它的结果,整个结果列表将会一次性映射进res。如果只有几千或更少的结果记录,一般来说不是什么大事。但假如有 1 千万个记录,那么就可能会花一段时间运行(在强大的笔记本电脑上花几秒钟,在移动设备上花的时间长得多,等等)。
当这样的“处理”运行时,页面上没有任何事情可以发生,包括不能有另一个**response(..)**调用,不能有 UI 更新,甚至不能有用户事件比如滚动,打字,按钮点击等。非常痛苦。
所以,为了制造协作性更强、更友好而且不独占事件轮询队列的并发系统,你可以在一个异步批处理中处理这些结果,在批处理的每一步都“让出”事件轮询来让其他等待的事件发生。
这是一个非常简单的方法:
1 |
|
我们以每次最大 1000 件作为一个块儿处理数据。这样,我们保证每个“进程”都是短时间运行的,即便这意味着会有许多后续的“进程”,在事件轮询队列上的穿插将会给我们一个响应性(性能)强得多的网站/应用程序。
当然,我们没有对任何这些“进程”的顺序进行互动协调,所以在res中的结果的顺序是不可预知的。如果要求顺序,你需要使用我们之前讨论的互动技术,或者在本书后续章节中介绍的其他技术。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!