在大多数情况下,我了解如何在承诺中包装异步和同步函数,以及这样做的好处和原因。但是,我不了解在浏览器中如何处理它们。
例如,如果依次调用两个同步函数(两个连续的语句),则第二个直到第一个返回时才开始。如果每个同步函数都包装在一个promise中,然后一个接一个地调用(不是另一个then
语句中的一个,而是两个连续的语句),那么同步函数现在是否要同时处理而不是按顺序处理?
我有充分的理由提出疑问,而不仅仅是对假设情景的兴趣。我正在开发一个扩展程序,该扩展程序在单个本地HTML页面中打开选项卡式显示。打开页面后,注入的脚本将打开indexedDB数据库并启动一组promise,该promise会检索每个选项卡的数据,并使用适当的数据填充每个选项卡的各个部分。将它们放在Promise.all
中给人的印象是,所有这些工作是同时进行的,并在检索数据时填充选项卡,而不是依次填充每个选项卡。
在多个单独的promise(每个选项卡一个promise)中,当事务完成时,将调用同步功能以在该选项卡的不同部分中显示数据。如现在所编码的,用于显示的同步函数在连续的语句中一个接一个地被调用,从而仅在第一个部分完成并返回之后才填充选项卡的第二个部分。因为整个事务已经完成,所以已经为所有部分检索了数据;因此,第二个显示功能不必等待第一个完成。如果将这些显示功能包装在promise中,并以此方式调用,那么是否会同时填充选项卡的两个部分?
可以对事务进行拆分,以使每个选项卡部分有一个事务,并且同步显示功能将在检索到其特定数据后立即启动;但是,我想每个标签保留一笔交易。
无论哪种方式,加载过程就足够了;但我想了解,即使用户看不见,将显示功能包装在Promise中是否也会导致同一标签中各个部分的并发填充。
也许,我只是感到困惑,尽管Promise和Promise.all
给人以并发进程的印象,但JavaScript中确实没有这种东西,而发生的一切是异步函数按其顺序依次处理活动完成。如果是这样,如上所述,将同步功能包装在Promise中,对于加快选项卡部分中的数据填充速度没有好处。
如果这是正确的,那么提高加载速度的唯一方法就是拆分交易;仅当事务中的数据检索步骤中的一个步骤比其他步骤花费的时间更长并且延迟了事务的完成和显示该数据的功能的启动时,这才有帮助。
对于这个问题的冗长,我深表歉意,如果由于没有代码可审查而被认为是不合适的,那么删除它肯定不会有问题。但是,如果您能以我的理解来解释我错了,我将不胜感激。 谢谢。
答案 0 :(得分:1)
Javascript是单线程的,因此JavaScript环境本身没有并发性。您的同步节填充功能将以先到先得的方式执行。
当您调用异步请求(例如网络请求承诺)(甚至是setTimeout
调用)时,该执行将分派到javascript环境之外的内核环境中进行处理,而无需在其中运行阻止js执行,并可能在单独的线程上运行。
返回时,容器(浏览器)通过将回调添加到消息队列中来将结果推回到同步javascript-land。当javascript调用堆栈为空时,事件循环将检查消息队列中是否有未决的回调。如果找到一个,则将其压入调用堆栈,以在下一个执行循环上执行。
首先返回的哪个节调用将首先执行,返回的任何其他异步调用都必须等到第一个调用完成后才能运行。
某处有一篇很棒的文章,它解释了所有这些如何比我能做的更好(更权威)。我将尝试找到它并使用链接更新我的答案。
更新:This post对此进行了很好的解释。