我认为这个问题很好,指出了重要的观点和考虑因素。
话虽如此,我认为问题的核心在于意图和理解开发人员(您)想要控制什么。
首先,名称sleep是一个重载的命名选择。即,“什么”将被“睡眠”;作为一名开发人员,我控制着什么?
在任何语言引擎中,在任何OS进程上运行,在任何裸机或托管系统上,“开发人员”都不控制(拥有)OS共享资源CPU内核(和/或线程),除非他们正在编写OS/process系统本身。CPU是一种时间共享资源,工作执行进度的货币是分配给系统上要执行的所有工作的“周期”。
作为一名应用程序/服务开发人员,最好考虑我是由操作系统进程/语言引擎管理的工作流活动流的控制者。在一些系统上,这意味着我控制一个本机os线程(可能共享CPU内核),在其他系统上,意味着我可以控制一个异步延续工作流链/树。
对于JavaScript,它是“后者”。
因此,当需要“睡眠”时,我打算让我的工作流在执行过程中“延迟”一段时间,然后再继续执行工作流中的下一个“步骤”(阶段/活动/任务)。
这是“恰当”的说法,即作为一个开发人员,最容易将模型作为线性代码流来工作;根据需要采用工作流的组合来进行缩放。
今天,在JavaScript中,我们可以选择使用高效的多任务20世纪80年代基于角色的延续架构(重新标记为现代Futures/Promises/then/await等)来设计这样的线性工作流。
考虑到这一点,我的答案不是提供新的技术解决方案,而是关注问题本身的意图和设计视角。
我建议,任何答案都要从思考上述概念开始,然后选择一个提醒和暗示意图的名字(而不是睡眠)。
工作流选择1:delayWorkForMs(nMsToDelay)选项2:delaySyncSequenceForMs(msPeriod)
async delayAsyncSequenceForMs(msPeriod) {
await new Promise(resolve => setTimeout(resolve, msPeriod));
}
请记住,任何异步函数都会返回Promise,await只能在异步函数中使用。(哈哈,你可能会问自己为什么……)。注意事项1:不要使用“循环”来消耗cpu周期。注意事项2:在JavaScript模型中,当在非异步函数中时,您不能“延迟”(等待)“异步”工作流的执行(除非您正在做不必要的坏事,而不需要占用cpu周期)。您只能在“异步”函数中“延迟”代码步骤。在内部,“异步”函数被建模为每个await关键字处的入口点/延续的集合。如果您熟悉倒勾插值模型,您可以“将await”视为在概念上建模,类似于编写倒勾字符串,如:
// Conceptualizing, using an interpolation example to illustrate
// how to think about "await" and "async" functions
`code${await then-restart-point}more-code${await then-restart-point}`