-
Notifications
You must be signed in to change notification settings - Fork 3
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
JS 问题清单 #155
Comments
PromisePromise = class extends Promise{
constructor(executor) {
super((resolve, reject) => {
executor(resolve, reject)
setTimeout(reject, 1000, new Error("timeout"))
})
}
}
new Promise(
(resolve, reject) => { }
).then(
res => console.log('then', res)
).catch(
err => console.log('catch', String(err))
) 这是一段从别处看来的 JS 代码,利用装饰器的思想,给自定义的 Promise 统一添加超时 reject。理顺这段代码,能让自己真正理解 Promise 的诸多细节。 |
async awaitJS 是天生的异步小能手,JS 运行时自带 event loop 统筹异步事件:
|
vue nextTicket这是一个 Vue 中很少使用的一个功能,但却不可或缺。原因是:
但这不是此功能值得深究的原因所在。理解此功能的实现原理有助于从细节和应用层面把握 JS 的异步队列机制。 现代 JS 的异步队列机制总体来说分为两种:
原则上来讲,每一个微任务队列都是在单个宏任务内部触发和消化完毕,除非采取特殊优化。 什么意思呢?每一个宏任务在执行过程中,会产生异步微任务队列,这个微任务队列是单个宏任务的一部分。这样是非常合理的:宏任务内部触发的微任务理应共享 environment state。 说实话,我理解这些东西的过程和我现在阐述它们的顺序刚好是反着的。 在试图把握 vue nextTicket 实现原理时,对宏任务,setTimeout,微任务, Promise,DOM mutation 这些概念还没有一个正确且基本的认识,我能做的就是不局限自己,通过各种积累不断拼凑出一个明晰的版图。 nextTicket 的目标:让函数在 dom update 之后执行,以及如果可能的话,在dom render 之前执行。 而 dom update 在 Vue 中是异步的,而且是微任务级别的异步,所以想要实现目标,只需要把函数封装在一个异步微任务中即可。 事情本来是如此简单,却又因为一件事变得复杂:不是所有 JS 宿主都完美支持微任务。 Why? 很简单:本来也确实完全可以没有微任务,原则上不妨碍任何事。这也正是上古浏览器 IE 的状态。 最终结论是:微任务是针对单个宏任务来讲的,如果没有微任务,完全可以退而求其次,使用宏任务来异步。vue nextTicket 必须实现的目标是 defer func execute after current dom update cycle, 所以能用微任务当然最好,能避免跨越浏览器渲染。没有的话,用宏任务也能实现目标,无非是不够及时,以及可能造成重复渲染。
看见没,vue nextTicket 和 dom update 的实现原理几乎完全一致:有微任务就用,没有的话就用宏任务来兜底,毕竟所有浏览器都支持 setTimeout 这个宏任务。 |
Zeros in JS+0 === -0 // true
Object.is(+0, 0) // true
Object.is(+0, -0) // false
1 / +0 === Infinity // true
1 / -0 === -Infinity // true |
"falsy" values list:
有且仅有这些。 对了,补充一点判断 NaN 的方式: Number.isNaN(v) 感受:JS 虽是极为灵活的动态类型语言,却又满身静态类型语言的残毒。最明显的一条:竟然学着 Java 区分所谓原始数据类型和对象数据类型。 为什么会有这种感受:JS 是 Brendan Eich 受雇于网景公司(Netscape),出于明确的商业目标,在管理层明确的靠近 Java,但又要区别于 Java 的要求之下,所设计的一种语言。 因此,JS 身上有了 Java 的影子,面向对象,但使用原型链实现。 Brendan Eich 的自主意志体现在:除却这些表面上的东西,JS 骨子里和 lisp 一脉相承。 更多细节参见:JS 诞生记 |
Event Loop and QueueThe Node.js Event Loop, Timers, and process.nextTick()
Analysis of Microtask and Macrotask in JS event cycle
判断下面代码的输出setTimeout(() => {
console.log('timeout');
}, 0);
let now = Date.now()
while (Date.now() - now < 3000) {}
setImmediate(() => {
console.log('immediate');
});
Promise.resolve().then(
() => console.log("promise 1")
).then(
() => console.log("promise 2")
) 答案是:需要看宿主环境对 在 Node 中,需要分情况,在非 IO 周期中,callback 的顺序不具有确定性。在 IO 周期内,始终是 setImmediate 在前。
所以针对 Node,即使如下恶性等待代码也会是先输出 const fs = require('fs');
fs.readFile('.', () => {
setTimeout(() => {
console.log('timeout');
}, 0);
let now = Date.now()
while (Date.now() - now < 3000) {}
setImmediate(() => {
console.log('immediate');
});
}); |
一个对 event loop 比较好的总结The more detailed algorithm of the event loop (though still simplified compare to the specification):
To schedule a new macrotask:
That may be used to split a big calculation-heavy task into pieces, for the browser to be able to react on user events and show progress between them. Also, used in event handlers to schedule an action after the event is fully handled (bubbling done). To schedule a new microtask
There’s no UI or network event handling between microtasks: they run immediately one after another. So one may want to |
知识清单,以点带面
现代 JS 教程:从基础到高阶
The JavaScript language
The text was updated successfully, but these errors were encountered: