js 不使用 promise 完成一个 sleep 函数,必须支持 await 调用

23 天前
 wefgonujnopu
有没有人会写的,看看 v 站有多少大神
要求:
await sleep(毫秒),让当前 async 函数进入等待,不能阻塞线程

提示: 实现起来非常简单,只要几行,不能使用任何库,要兼容浏览器环境
8795 次点击
所在节点    JavaScript
148 条回复
accelerator1
22 天前
@accelerator1 #138 我觉得这类问题挺好的,那些有异议的人应该先写出来、解释清楚再去反驳,"Talk is cheap, show me the code"。
accelerator1
22 天前
@wefgonujnopu #139 我也只是说明原理,并不是回答问题,在 js 单线程实现下,不阻塞的 sleep 只能宏任务 api ,相对不是那么准而已;想要准确的 sleep ,只能阻塞方式。题目说是实现 sleep ,其实更关注的其实是避免栈溢出。
zangbianxuegu
22 天前
主题目 thenable 考察和附言的阻塞、堆栈溢出没什么关系。
为什么 js 的 sleep 不会导致堆栈溢出,这其实是和**事件循环**相关,**事件循环是浏览器的机制**。
可以看我这篇文章,以及里面大佬的视频演讲: https://mp.weixin.qq.com/s/MzAAa4ohk-75BHqGRH1XWQ

简单说因为 sleep 实现用的是 setTimeout ,比如:

```js
function loop() {
setTimeout(loop, 0);
}
loop();
```
这段代码永远不会导致浏览器卡死,setTimeout 创建任务加入任务队列,setTimeout 执行完会让出主线程控制权,进行渲染和其他任务。
zangbianxuegu
22 天前
既说了不能阻塞线程,又觉得它不会造成堆栈溢出是不对的。这不是矛盾吗?
wefgonujnopu
22 天前
@zangbianxuegu 你错了,和 setTimeout 没关系,你看这段代码有 setTimeout 么,为什么也不会溢出
···
async function foo() {
return 1
}


async function main(num = 0) {
//去掉 foo 会堆栈溢出
await foo()
await main()

}

main()


···
zangbianxuegu
22 天前
@wefgonujnopu #145
不错,我说矛盾的说法也不准确。微任务确实不阻塞代码执行,也不会造成调用栈溢出。

有 `await foo()` 不会导致堆栈溢出是因为,await 创建微任务,main() 当前的调用栈被清空,每一次都会被清空不会累加,所以不会出现:Maximum call stack size exceeded

以上是在 Node 环境中。

在浏览器环境中,有没有 `await foo()` 都会导致浏览器的卡死,因为阻塞渲染。
chanderbing
22 天前
感觉自己实现过 promise 的都能一秒想到吧,因为实现的时候就要对 thenable 对象进行处理。https://github.com/childrentime/wheel/blob/main/src/promise/index.js#L139-L158
LawlietZ
20 天前
@lscho 刚学 js 的最喜欢鼓捣这些了,因为面试,然后有经验的人来回答,闭环了,有经验的人做面试官有时候也出这种面试题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1140531

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX