javascript - javascript回调中的实际运行时是什么
问题描述
我正在尝试理解 JS 回调。在下面的示例中,A 是在 100 毫秒后执行还是立即执行?
每个 A、B、C 执行的实际时间是多少?0 毫秒:“A”(或 100 毫秒?) 100 毫秒:“C”,100 毫秒:“B”
function wait(ms) {
let waitUntil = Date.now() + ms
while (Date.now() < waitUntil) { continue }
}
document.querySelector('#start-button').onclick = () => {
console.log('A')
setTimeout(() => {
console.log('B')
}, 50)
wait(100)
console.log('C')
}
如果将其修改为:
function wait(ms) {
let waitUntil = Date.now() + ms
while (Date.now() < waitUntil) { continue }
}
document.querySelector('#start-button').onclick = () => {
console.log('A')
setTimeout(() => {
console.log('B')
}, 150) // 150ms instead of 50ms
wait(100)
console.log('C')
}
实际运行时间是多少?是0ms:A 100ms:C 150ms:B(或100ms+150ms=250ms)
解决方案
我冒昧地为您提供了可运行的功能。我还大幅增加了延迟以更清楚地说明这一点。您可以看到,在单击开始按钮后,实际上直到整个 lambda onclick 函数完成其执行后,您才能将任何输出输出到控制台,直到阻塞线程的等待调用完成后才能执行此操作。但是,A 日志语句确实首先执行,并且其时间戳比 C 语句早了整整 2 秒。
有趣的是,B 语句的 setTimeout 延迟实际上被忽略并被阻塞线程的等待语句所取代。在等待块完成后触发该函数时会引入 <10ms 的小延迟。但是,如果您将等待延迟降低到小于给定 setTimeout 的延迟,它会在给定的时间延迟之后执行。
所以时间看起来是这样的:
A: 0, but it's printed after the wait delay
C: the wait delay
B: the wait delay + <10ms
还值得注意的是,块的执行时间可能会在这里或那里增加额外的毫秒,正如您通过运行块所看到的那样。如果您的延迟是 200 毫秒,那么它很可能会显示 201 毫秒的日志时间。如果块变得更复杂并且需要更长的执行时间,这种效果将变得更加明显。
function wait(ms) {
let waitUntil = Date.now() + ms
while (Date.now() < waitUntil) { continue }
}
document.querySelector('#start-button').onclick = () => {
console.log('A', Date.now())
setTimeout(() => {
console.log('B', Date.now())
}, 500)
wait(2000)
console.log('C', Date.now())
}
<button id="start-button">Start</button>
这是较短的等待电话。
A: 0, but it's printed after the wait delay
C: the wait delay
B: 500ms
function wait(ms) {
let waitUntil = Date.now() + ms
while (Date.now() < waitUntil) { continue }
}
document.querySelector('#start-button').onclick = () => {
console.log('A', Date.now())
setTimeout(() => {
console.log('B', Date.now())
}, 500)
wait(200)
console.log('C', Date.now())
}
<button id="start-button">Start</button>
推荐阅读
- java - 从包含库的模块提供库版本
- mysql - 无法从 PhpStorm 远程连接到 KINSTA 站点的 MySQL
- javascript - 嵌套路由器视图未显示;视图组件未安装
- swiftui - 如何将 FSCalendar 数据从 UIKIT 传递到 SwiftUI
- amazon-web-services - 如何使用 CSVSERDE 在同一个配置单元表中加载 2 个 CSV 文件
- deep-learning - IndexError:索引 2047 超出轴 0 的范围,大小为 1638
- python - 使用 pandas 将每 n 行从一列转置为多列
- julia - 如何在 Julia 的 Turing 模块中使用 CDF 函数?
- r - plotly line plots:使其中一个粗体
- java - 解析网站,查找图片链接并下载 png