毫无疑问,谷歌在 2023 年将重点关注响应能力。
到目前为止,他们:
- 将“与下一次绘画的互动”从实验性移至待定状态;
- 宣布 INP 将于 2024 年 3 月取代首次输入延迟成为响应能力的新核心 Web 重要指标;
- 开始在 Search Console 中标记INP 问题,并向未达到良好响应阈值的网站发送电子邮件;
- 2024年3月12日,INP正式取代FID成为新的响应能力指标。
现在,Chrome 团队宣布他们目前正在对新的调度程序 API – scheduler.yield()进行原始试验。
scheduler.yield()有望为开发人 Mint 数据库 员提供一种更简单、更好的方法将控制权交还给主线程,从而帮助他们提高网站的响应能力。
继续阅读以了解有关新 API 。
快速回顾长任务和主线程
如果您清楚什么是长任务和主线程,请跳过此部分。如果不了解,我们建议您阅读此快速回顾,因为它是理解scheduler.yield()及其实现方法的基础。
浏览器所做的一切都被视为任务。这包括渲染、解析 HTML 和 CSS、运行您编写的 JavaScript 代码,以及其他您可能无法直接控制的事情。
主线程是浏览器完 您可以使用简单的工具和拖放界面自定义模板 成大部分工作的地方。
不幸的是,主线程每次只能处理一个任务。如果一个任务运行时间超过 50ms,则被视为长任务。
遇到耗时较长的任务意味着浏览器会尽可能长时间地运行该任务直至完成。完成后,控制权将交还给主线程,让浏览器处理队列中的下一个任务。
耗时任务是页面响应速度慢的主要原因,因为它们会延迟浏览器响应用户输入的能力。此外,JavaScript 的运行至完成模型是阻塞主线程的罪魁祸首。
这就是为什么它被认为 B2B 传真线索 是一种阻止渲染的资源——当浏览器遇到它时,它必须先下载、解析和执行它,然后再做任何其他事情。
好消息是,仅仅因为您的代码在浏览器中启动了一项任务并不意味着您必须等到该任务完成后才能将控制权返回到主线程。
您可以通过在任务中明确放弃来分解较长的任务。
简单来说,任务让步可以确保浏览器不会过于专注于一项任务而错过或延迟响应其他重要任务或用户交互。
不幸的是,当前的收益策略并不完美……
为什么使用 scheduler.yield():当前收益策略的问题
让步到主线程并不是一个新概念。开发人员一直在使用不同的让步策略来分解长任务:
1. 设置超时时间
setTimeout()允许您安排任务在指定的延迟后或以固定的间隔运行。即使您指定的超时时间为 0,这也会将回调的执行推迟到单独的任务中。当您有多个应相继运行的函数时,此方法非常有效。
缺点:无法保证精度。由于队列中还有其他任务,回调可能无法在指定的延迟后准确运行。此外,如果您在循环中处理大量数据集,则该任务可能会变得非常耗时,尤其是在有数百万个条目的情况下。
2. requestIdleCallback()
requestIdleCallback()允许您安排任务在浏览器可能存在的任何空闲期间运行。它对于执行非紧急任务而不影响用户体验非常有用。
缺点:requestIdleCallback()以最低优先级安排任务,这意味着如果主线程拥挤,安排的任务可能永远无法运行。
3. isInputPending()
isInputPending()可以随时执行,以检查用户是否正在尝试与页面上的元素交互。如果是,则该函数返回true;如果不是,则返回false。
假设您有一系列任务要执行,但又不想打断用户交互。您可以使用isInputPending()和YieldToMain()函数来确保用户输入在与页面交互时不会延迟。
缺点:isInputPending()可能不会总是在用户输入后立即返回 true。这是因为操作系统需要时间来告知浏览器交互已发生。这意味着其他代码可能已经开始执行。
这些是一些常用的让出主线程的方法。如你所见,每种方法都有自己的缺点。
但最显著的缺点是:
当您通过推迟代码以在后续任务中运行来让位于主线程时,该代码将被添加到任务队列的最后。
这为什么是一个问题?
答案有三点:
- 逻辑错误的可能性增加:由于延迟代码位于任务队列的末尾,因此浏览器在返回延迟任务之前可能会执行其他任务。这可能会影响函数执行的顺序,并可能导致逻辑错误或意外行为。
- 执行延迟:如果队列中有很多任务,浏览器可能需要很长时间才能执行延迟的代码。
- 不可预测性:很难准确预测延迟任务何时运行,因为这取决于队列中已有任务的数量和性质。这种不可预测性可能会使调试和性能优化变得具有挑战性。
总而言之,虽然使用当前策略让出主线程可以帮助维护响应式用户界面,但也会带来确保代码及时有序执行的挑战。