【问题标题】:block execution by delay function javascript通过延迟函数javascript阻止执行
【发布时间】:2021-01-21 23:57:55
【问题描述】:

我正在使用以下代码查看 JavaScript 执行是否在同步函数进入长循环时被阻塞。

function delayBySeconds(sec){
  let start = now = Date.now();
  while((now - start) < (sec * 1000)){
    //console.log(now);
    now = Date.now();
  }
}

const seconds = 20;
delayBySeconds(seconds);
console.log(`${seconds} seconds passed`);

它立即打印消息,表明执行不等待被调用函数完成其循环。这是如何运作的?我的意思是如果 delayBySeconds 函数正常工作,消息如何立即打印?这只是实验性的,当然,我会用它来做一些实际的延迟是没有意义的。

【问题讨论】:

标签: javascript asynchronous delay callstack event-loop


【解决方案1】:

这是一个同步代码执行。控制台一直在等待,直到函数未完全执行。您没有看到任何延迟,因为您没有在循环内执行任何任务。

如果您在 while 循环中取消注释控制台,您可以看到延迟。

【讨论】:

  • 赋值语句(now = Date.now())如何不执行任务?甚至一会儿(1);正在执行一项任务。不过,我发现了真正的问题。实际上,我在jsbin.com 在线编辑器上尝试了这段代码。当我在自己的 PC 上的独立浏览器中尝试它时,它起作用了。它会阻塞执行指定的秒数。所以一个教训是,如果任何一段 JS 代码意外执行,请检查它是一个独立的浏览器。
  • 是的,你是对的。 jsbin 控制台不同于浏览器控制台。如果您在浏览器控制台中尝试过,它将停止执行。
【解决方案2】:

由于 JavaScript 始终是同步的和单线程的,它不会等待您的函数执行完成,然后再继续执行下一条语句。因此,为了正确等待函数完成执行,我们使用 Promise/Then 之类的“框架”对函数进行异步调用,即在继续之前等待它完成。现在在 ES2017 之后,我们可以使用 async/await 来简化流程。

使用 Promise 的片段

const delayBySeconds = sec => new Promise(resolve => {
  let start = now = Date.now();
  while((now - start) < (sec * 1000)){
    // console.log(now - start);
    now = Date.now();
  }
  resolve()
})

const seconds = 10;
delayBySeconds(seconds).then(()=>
console.log(`${seconds} seconds passed`))

sn-p 使用异步/等待

const delayBySeconds = async sec => {
  let start = now = Date.now();
  while((now - start) < (sec * 1000)){
    // console.log(now - start);
    now = Date.now();
  }
  return
}

const main = async () => {
  const seconds = 7;
  await delayBySeconds(seconds)
  console.log(`${seconds} seconds passed`)
}

main()

注意 async/await 只能用在 async 函数中,所以如果你使用的是原生 js,你必须把它包装在一个函数中。但是,有些,例如 Deno,一个相当新的后端 js 框架,对 async/await 具有全局支持,因此您不必将其包装在其中。

【讨论】:

  • 另外,我不会批评代码,因为这只是您的实验,但请注意,像这样的 while 循环会浪费大量计算资源,因为它会检查一秒钟是否通过了数百次每秒的次数。请参阅link 以获得更好的sleep 替代方案
  • 是的,我明白这不是一个实用的代码。请参考我对 Sawan Nirala 上一个回答的回复
  • 希望对您有所帮助,如果有帮助,也许您可​​以将我的回答标记为已接受,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
  • 2018-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-02
  • 1970-01-01
相关资源
最近更新 更多