关于eventloop:深入理解JavaScript之彻底弄懂JsEventLoop执行机制

JavaScript单线程起源:JavaScript作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM,为了防止复杂性,诞生开始,JavaScript就是单线程语言。比方,假设JavaScript同时有两个线程,一个线程在某个DOM节点上增加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?所以,为了防止复杂性,从一诞生,JavaScript就是单线程。 单线程及存在的问题:单线程就意味着,所有工作须要排队,前一个工作完结,才会执行后一个工作。如果前一个工作耗时很长,后一个工作就不得不始终等着。 问题的解决--同步、异步synchronous(同步工作)和asynchronousk(异步工作)同步工作是调用立刻失去后果的工作,同步工作在主线程上排队执行的工作,只有前一个工作执行结束,能力执行后一个工作;异步工作是调用无奈立刻失去后果的工作,须要额定的操作能力预期后果的工作,异步工作不进入主线程、而进入"工作队列"(task queue)的工作,只有"工作队列"告诉主线程,某个异步工作能够执行了,该工作才会进入主线程执行。macro-task(宏工作)和micro-task(微工作)宏工作:macro-task 能够了解是每次执行栈执行的代码就是一个宏工作(包含每次从事件队列中获取一个事件回调并放到执行栈中执行,每一个宏工作会从头到尾将这个工作执行结束,不会执行其它)包含整体代码script,setTimeout,setInterval等微工作:micro-task能够了解是在以后 task 执行完结后立刻执行的工作 包含Promise,process.nextTick等(未完...)

June 30, 2022 · 1 min · jiezi

关于eventloop:爪哇学习笔记宏任务微任务

JavaScript运行时在执行 JavaScript 代码的时候,JavaScript 运行时实际上保护了一组用于执行 JavaScript 代码的代理。每个代理由一组执行上下文的汇合、执行上下文栈、主线程、一组可能创立用于执行 worker 的额定的线程汇合、一个工作队列以及一个微工作队列形成。除了主线程(某些浏览器在多个代理之间共享的主线程)之外,其它组成部分对该代理都是惟一的事件循环(Event Loops)每个代理都是由事件循环驱动的,事件循环负责收集用事件(包含用户事件以及其余非用户事件等)、对工作进行排队以便在适合的时候执行回调。而后它执行所有处于期待中的 JavaScript 工作(宏工作),而后是微工作,而后在开始下一次循环之前执行一些必要的渲染和绘制操作。(本节文字来自mdn,集体感觉形容有误,具体程序往下看)Event Loops中,每一次循环成为tick,每次tick的流程如下: 执行主线程中的同步代码(能够看做一个宏工作),直到执行实现查看微工作队列,若不为空,则执行微工作队列中的所有微工作,直到队列为空查看宏工作队列中在以后tick之前退出到队列中的宏工作,顺次执行没执行完一个宏工作,反复顺次第二个步骤当微工作队列已清空且宏工作队列中以后tick之前退出的宏工作都已执行实现,执行一些别要的渲染和绘制工作(宿主环境为浏览器时)完结以后tick,进入下一个tick分类Window 事件循环Worker 事件循环Worklet 事件循环宏工作&微工作一个工作(宏工作)就是指打算由规范机制来执行的任何 JavaScript,如程序的初始化、事件触发的回调等。 除了应用事件,你还能够应用 setTimeout() 或者 setInterval() 来增加工作。起初微工作和工作之间的差别看起来不大。它们很类似;都由位于某个队列的 JavaScript 代码组成并在适合的时候运行。宏工作和微工作的区别当执行来自工作队列中的工作时,在每一次新的事件循环开始迭代的时候运行时都会执行队列中的每个工作。在每次迭代开始之后退出到队列中的工作须要在下一次迭代开始之后才会被执行.每次当一个工作退出且执行上下文为空的时候,微工作队列中的每一个微工作会顺次被执行。不同的是它会等到微工作队列为空才会进行执行——即便中途有微工作退出。换句话说,微工作能够增加新的微工作到队列中,并在下一个工作开始执行之前且以后事件循环完结之前执行完所有的微工作。创立路径宏工作: 程序的初始化事件触发的回调setTimeout()/setInterval()postMessage, MessageChannelsetImmediate() node环境微工作: PromiseMutaionObserverObject.observe(已废除,被Proxy对象代替)process.nextTick() node环境queueMicrotask()代码示例setTimeout(() => { console.log(3); // 在执行宏工作时退出宏工作,退出的宏工作会在下个tick执行 setTimeout(() => { console.log(8); }); // 在执行宏工作时退出微工作,以后宏工作执行实现后,立刻执行该微工作 new Promise(resolve => { resolve(); console.log(4); }).then(() => { console.log(6); }); // 在执行宏工作时退出宏工作,退出的宏工作会在下个tick执行 setTimeout(() => { console.log(9); }); console.log(5);});setTimeout(() => { console.log(7);});new Promise(resolve => { resolve(); console.log(1);}).then(() => { console.log(2);});// 输入后果:// 1// 2// 3// 4// 5// 6// 7// 8// 9参考文档: ...

January 17, 2022 · 1 min · jiezi

关于eventloop:前端笔记杂项二

宏工作与微工作宏工作 每次执行栈执行的代码就是一个宏工作(包含每次从事件队列中获取一个事件回调并放到执行栈中执行)。浏览器为了可能使得JavaScript外部宏工作与DOM工作可能有序的执行,**会在一个宏工作执行完结后,在下一个宏工作执行开始前,对页面进行从新渲染**。宏工作包含:**script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境)**微工作 **能够了解是在以后 task 执行完结后立刻执行的工作**。也就是说,在以后task工作后,下一个task之前,在渲染之前。微工作的响应速度相比宏工作会更快,因为无需等渲染。也就是说,在某一个宏工作执行完后,就会将在它执行期间产生的所有微工作都执行结束(在渲染前)。微工作次要蕴含:**Promise.then、MutaionObserver、process.nextTick(Node.js 环境)**Set向 Set 退出值的时候,不会产生类型转换,所以5和"5"是两个不同的值 扩大运算符(...)外部应用for...of循环 WeakSet * WeakSet 的成员只能是对象,而不能是其余类型的值。 * WeakSet 中的对象都是弱援用,即垃圾回收机制不思考 WeakSet 对该对象的援用,也就是说,如果其余对象都不再援用该对象,那么垃圾回收机制会主动回收该对象所占用的内存,不思考该对象还存在于 WeakSet 之中 MapObject 构造提供了“字符串—值”的对应,Map 构造提供了“值—值”的对应,是一种更欠缺的 Hash 构造实现 React HooksuseState * `setState` 函数用于更新 state。它接管一个新的 state 值并将组件的一次从新渲染退出队列。在后续的从新渲染中,`useState` 返回的第一个值将始终是更新后最新的 state。 * 惰性初始 state:`initialState` 参数只会在组件的初始渲染中起作用,后续渲染时会被疏忽。如果初始 state 须要通过简单计算取得,则能够传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用 * 跳过 state 更新:调用 State Hook 的更新函数并传入**以后**的 state 时,React 将跳过子组件的渲染及 effect 的执行。(React 应用 [`Object.is` 比拟算法](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description) 来比拟 state。) * `useState` 不会主动合并更新对象: setValue(prevState => { // 也能够应用 Object.assign return {...prevState, ...updatedValues}; }); useEffect ...

April 9, 2021 · 1 min · jiezi

关于eventloop:从event-loop规范探究javaScript异步及浏览器更新渲染时机

异步的思考event loops暗藏得比拟深,很多人对它很生疏。但提起异步,置信每个人都晓得。异步背地的“靠山”就是event loops。这里的异步精确的说应该叫浏览器的event loops或者说是javaScript运行环境的event loops,因为ECMAScript中没有event loops,event loops是在HTML Standard定义的。 event loops标准中定义了浏览器何时进行渲染更新,理解它有助于性能优化。 思考下边的代码运行程序: console.log('script start');setTimeout(function () { console.log('setTimeout');}, 0);Promise.resolve() .then(function () { console.log('promise1'); }) .then(function () { console.log('promise2'); });console.log('script end'); 下面的程序是在chrome运行得出的,乏味的是在safari 9.1.2中测试,promise1 promise2会在setTimeout的后边,而在safari 10.0.1中失去了和chrome一样的后果。为何浏览器有不同的体现,理解tasks, microtasks队列就能够解答这个问题。 很多框架和库都会应用相似上面函数: function flush() {...}function useMutationObserver() { var iterations = 0; var observer = new MutationObserver(flush); var node = document.createTextNode(''); observer.observe(node, { characterData: true }); return function () { node.data = iterations = ++iterations % 2; };}首次看这个useMutationObserver函数总会很有纳闷,MutationObserver不是用来察看dom的变动的吗,这样凭空造出一个节点来重复批改它的内容,来触发察看的回调函数有何意义? ...

January 14, 2021 · 5 min · jiezi