
我们作为受欢迎网站的所有者的地位以及我们对受欢迎的React平台的支持工作使我们获得了独特的机会和对与我们要用来解决“队列”问题的浏览器一起使用的理解。 作为Web标准社区(W3C)的活跃成员,我们参与了许多创新的讨论,包括服务工作者和CSS过度滚动 ,但直到最近,我们才制定了自己的计划来改进Web浏览器。 为了实现生产率的显着提高,提出了一个新的API,作为与Google Chrome浏览器同事的密切合作的结果,该API提供了试用版 。 Chrome v74将包含isInputPending API ,可用于改善整体JavaScript执行时间和事件响应时间。 这只是改善Web上JavaScript计划的第一步。 我们希望获得开发人员的反馈,并使用它们来创建API的最终版本。
现代网络中最重要的性能指标之一是响应用户事件(单击按钮或进入字段)所需的时间,并具有完整的可视化效果。 在Facebook上,我们分四个阶段共享和评估事件:
- 操作系统接收数据
- 实际开始加工
- 开始在屏幕上显示更改以响应事件
- 处理完成,结果可视化
当我们评估我们最有生产力的产品时,注意到队列中的等待时间会带来最大的延迟。 排队是指用户与页面进行交互(例如,单击或点击)与开始实际处理事件之间的时间。 在某些情况下,这种延迟可能非常严重。 想象一下,您单击通知图标,然后等待一分钟,按钮才会响应。 可能没有人会等待答案。
快速启动或快速响应:选择一种
在快速页面加载和交互性之间很难进行权衡。 如果网站需要JavaScript,一种选择是将其全部运行在一个块中。 但这会产生问题。 Web浏览器中的JavaScript机制通常是单线程的,也就是说,它们一次只能在每个页面上执行一项操作。 在加载页面的情况下,这意味着如果用户单击某项,浏览器必须将click事件排队,直到启动整个JavaScript块。
像许多其他站点一样,我们通过将JavaScript分成小块来解决此问题。 在页面加载期间,我们启动一些JavaScript,然后将控制权返回给浏览器。 然后,浏览器可以检查输入事件队列,并查看是否有任何要处理的内容。 然后,浏览器可以在添加它们时返回运行中的JavaScript块。 这会有所帮助,但可能会导致其他问题。 每次我们将控制权返回给浏览器时,都会花费一些时间来检查输入事件的发生,处理事件以及选择下一个JavaScript块。 因此,尽管浏览器对事件的响应速度更快,但是我们仍然需要在代码块的大小和劣于浏览器的频率之间找到平衡。 如果我们过于频繁地更改控件,则页面加载速度太慢;相反,如果加载频率降低,浏览器将花费更多时间来响应用户事件,并且人们会感到失望。

如果我们运行较大的JavaScript块,则浏览器可能会延迟很长时间(如上所述)发送用户事件; 如果我们运行较小的块,则页面需要更长的时间加载(底部)。
当我们第一次发现队列中的延迟时,我们求助于Chrome中的同事。 我们想看看如果我们想出一种新的下载方法来消除这种折衷的困境,一切将会如何。 与他们交谈后,我们建议isInputPending。 isInputPending API是第一个将中断的概念用于Web用户事件的API 。
在幕后 , isInputPending在编译器端的Chrome输入队列上侦听以捕获事件,然后再将事件添加到主流中。 由于此侦听是在主线程之外执行的,因此isInputPending调用不会消耗大量计算资源,并且应该非常快。 这使开发人员可以频繁调用API并最大化响应速度。
一旦准备好该提案,我们便转向W3C Web性能工作组,并获得了各种浏览器供应商的同意,我们的想法值得探讨。 将来,我们将与Chrome中的同事合作,独立实施新的API,并在Chrome中发送相应的代码修复。 感谢Chrome的工程师,我们获得了试用补丁,使我们可以测试更改并在完整版本发布之前获得开发人员的反馈。 此版本将使我们能够了解此API对开发人员的重要性,并确定我们与Web浏览器提供商有关此API的未来对话。 这是我们第一次经历开发Web API的所有阶段,从在论坛上讨论提案到将代码传递到Web浏览器。
顾名思义, isInputPending会告诉您是否有等待输入的事件。 开发人员可以在运行JavaScript时使用此信息来决定是否要重新获得对浏览器的控制。 正确使用isInputPending可以完全消除快速加载和交互性的难题。
要使用API,请使用navigator.scheduling.isInputPending()
。 本质上,如果浏览器期望事件被调度,则此方法返回true
。 不带任何参数调用时,将检查所有受支持的事件类型。 此外,可以手动指定事件类型的列表:鼠标,滚轮,触摸,应检查这些事件的未决输入。
示例:检查任何类型的事件
while (workQueue.length > 0) { if (navigator.scheduling.isInputPending()) { // break; } let job = workQueue.shift(); job.execute(); }
示例:检查特定的输入事件
while (workQueue.length > 0) { if (navigator.scheduling.isInputPending(['mousedown', 'mouseup', 'keydown', 'keyup'])) { // 'mousedown' 'mouseup' 'keydown' 'keyup' break; } let job = workQueue.shift(); job.execute(); }
接下来是什么?
如果社区反馈是肯定的,则isInputPending可能会在Chrome中完全可用。 然后,我们可以消除队列中这些明显的延迟,并使Internet上的工作对于站点上的人员而言更快,更灵活。 对于还希望摆脱队列延迟并改善交互和下载性能的开发人员,将很快提供试用版。 请在此处注册并在试用版可用后立即分享您的意见。
Chrome的isInputPending移植过程是在Facebook上开发Web标准的新方法。 我们希望继续开发新的API,并增加对开源Web浏览器的贡献。 将来,我们可能会将此API直接嵌入React中,以便开发人员可以立即使用该API。 另外, isInputPending现在是创建用于在网络上进行规划的原语的出色工作的一部分。 我们希望继续与Chrome保持合作关系。 最后,我们希望看到浏览器工具,这些工具将允许开发人员将其更深入地集成到浏览器任务队列中,甚至允许开发人员了解各种网络请求和任务的浏览器优先级。
作者注
要尝试新的API,您需要: