try 里面放 return,finally 里的代码会不会执行,理解其内部机制
会执行,在方法返回给调用者前执行,因为如果存在finally
代码块,try
中的return
语句
不会立马返回给调用者,而是记录下返回值待finally
代码块执行完毕之后再返回;
1 | // return 执行了但是没有立即返回,而是先执行了 finally |
1 | // finally 中的 return 覆盖了 try 中的 return。 |
注意
1、不管有木有出现异常,finally
块中代码都会执行;
2、当 try
和 catch
中有 return
时,finally
仍然会执行;
3、finally
是在 return
后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,不管 finally
中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在 finally
执行前确定的;
4、finally
中最好不要包含 return
,否则程序会提前退出,返回值不是 try
或 catch
中保存的返回值。
JavaScript 如何实现异步编程
1.回调函数
但会导致两个问题:
缺乏顺序性: 回调地狱导致的调试困难,和大脑的思维方式不符
缺乏可信任性: 控制反转导致的一系列信任问题
2.PromisePromise
是基于 PromiseA+
规范的实现,它很好的解决了控制反转导致的信任问题,将代码执行的主动权重新拿了回来。
3.生成器函数 Generator
使用 Generator
,可以让我们用同步的方式来书写代码,解决了顺序性的问题,但是需要手动去控制 next(...)
,将回调成功返回的数据送回 JavaScript 主流程中。
4.Async/AwaitAsync/Await
结合了 Promise
和 Generator
,在 await
后面跟一个 Promise
,它会自动等待 Promise
的决议值,解决了 Generator
需要手动控制 next(...)
执行的问题,真正实现了用同步的方式书写异步代码。
5.发布订阅模式
在 JavaScript
中应用非常广泛,比如一些前端框架比如 React,Vue 等,都有使用这一设计模式,nodejs
使用的就更多了。
使用发布订阅模式的好处是事件集中管理,修改方便,缺点就是,代码可读性下降,事件容易冲突。
简单实现
1 | //async_Event.js |
简单使用
1 | //注册事件,名为event |
宏任务和微任务分别有哪些
宏队列,macrotask
,也叫 tasks
。 一些异步任务的回调会依次进入 macro task queue
,等待后续被调用,这些异步任务包括:
1 | setTimeout |
微队列,microtask
,也叫 jobs
。 另一些异步任务的回调会依次进入 micro task queue
,等待后续被调用,这些异步任务包括:
1 | process.nextTick (Node独有) |
使用 Promise 实现串行
1 | // 一个 promise 的 function |
1.reduce
1 | arr.reduce((s, v) => { |
2.async + 循环 + await
1 | ;(async function() { |
3.普通循环
1 | let p = Promise.resolve() |
4.递归
1 | function dispatch(i, p = Promise.resolve()) { |
EventLoop 是什么
event loop
是一个执行模型,在不同的地方有不同的实现。浏览器和 NodeJS
基于不同的技术实现了各自的 Event Loop
。
浏览器的 Event Loop
这张图将浏览器的 Event Loop 完整的描述了出来,我来讲执行一个 JavaScript 代码的具体流程:
1 | 1.执行全局Script同步代码,这些同步代码有一些是同步语句,有一些是异步语句(比如setTimeout等); |
这里归纳 3 个重点: 1.宏队列macrotask
一次只从队列中取一个任务执行,执行完后就去执行微任务队列中的任务; 2.微任务队列中所有的任务都会被依次取出来执行,知道microtask queue
为空; 3.图中没有画UI rendering
的节点,因为这个是由浏览器自行判断决定的,但是只要执行UI rendering
,它的节点是在执行完所有的microtask
之后,下一个macrotask
之前,紧跟着执行UI render
。
测试一下你是否掌握了:
1 | console.log(1) |
这里结果会是什么呢?运用上面了解到的知识,先自己做一下试试看。
1 | // 正确答案 |
参考资料: 带你彻底弄懂 Event Loop
如何解决页面加载海量数据而页面不卡顿
1.分治思想,在一定的时间内多次加载数据,直至渲染完成,使用 window.requestAnimationFrame
和 document.createDocumentFragment()
实现
2.局部显示,毕竟用户能看到的就一屏内容,监听用户的滚动行为,改变显示元素,可使 DOM
结构最简单化
题目:页面上有个空的无序列表节点 ul ,其 id 为 list-with-big-data ,现需要往列表插入 10w 个 li ,每个列表项的文本内容可自行定义,且要求当每个 li 被单击时,通过 alert 显示列表项内的文本内容
1 |
|
解决方案
1 | ;(function() { |