jQuery如何拥有异步函数?
Posted
技术标签:
【中文标题】jQuery如何拥有异步函数?【英文标题】:How does jQuery have asynchronous functions? 【发布时间】:2012-04-07 13:59:50 【问题描述】:我很惊讶我找不到明确的答案。所以,在 jQuery 中,你可以这样做:
$(someElements).fadeOut(1000);
$(someElements).remove();
这将启动一个淡出动画,但在它在 1 秒的持续时间内完成执行之前,元素会从 DOM 中删除。但这怎么可能?我一直在阅读 javascript 是单线程的(另请参阅:Is JavaScript guaranteed to be single-threaded?)。我知道我可以做到:
$(someElements).fadeOut(1000).promise().done(function()
$(someElements).remove();
);
甚至更好:
$(someElements).fadeOut(1000, function()
$(this).remove();
);
我不明白 JavaScript 是如何在“单线程”中运行的,但我可以使用这些异步执行的 jQuery 函数,并且可以同时在不同的地方看到 DOM 的变化。它是如何工作的? 这个问题不是:“我该如何解决这个问题”。
【问题讨论】:
简答:CSS 动画或计时器。 我认为是因为 jQuery 使用队列来制作动画,它在文档中的某个地方.. 【参考方案1】:jQuery 动画(以及几乎所有基于 javascript 的动画)使用计时器来运行它们的动画。对.fadeOut()
的调用只是启动动画,直到一段时间后一系列计时器操作完成后才会完成。
这仍然是单线程的。 .fadeOut()
执行动画的第一步,它为下一步设置一个计时器,然后你的 javascript 的其余部分(包括 .remove()
)运行直到完成。当该javascript线程完成并且计时器的时间过去时,计时器将触发并且动画的下一步发生。最后,当动画的所有步骤都完成时,jQuery 调用动画的完成函数。这是一个回调,允许您在动画完成时执行某些操作。
这就是您解决此问题的方法:
$(someElements).fadeOut(1000, function()
$(this).remove();
);
您使用动画完成功能,并且仅在动画完成后删除项目。
【讨论】:
如果您想要异步执行,您可以考虑使用 Web Worker 或使用(当前)实验性 River Trail OpenCL 桥接器(如果您正在进行密集的数据处理)。 我其实更喜欢 JSTween,因为它可以处理任何属性。 @FlavorScape - Web Worker 无法与 DOM 交互,因此它们对动画没有太大帮助。 你可以用它来计算多体复杂动画,其中每一帧都比补间更强烈。然后,您可以收集最终数据并在结果返回时在更新周期中更新坐标。不过我更喜欢 River Trail/OpenCL,它应该很快就会为 webkit/ff/chrome 标准化【参考方案2】:jQuery 中有一个 setInterval 处理程序,它对所有注册的动画属性执行转换。如果您来自 as3,请将其视为 EnterFrame 处理程序,或 OpenGL 中的 Draw 方法
【讨论】:
我认为在最近的 jQuery 版本中,它可能会使用 requestAnimationFrame 处理程序(由浏览器调度的事件)作为更新/绘制函数 requestAnimationFrame 已经进出 jQuery。它存在了一段时间,然后因为一些问题被撤掉了。我目前没有在我开源的 1.7 版本中看到它。 @jfriend00 你是对的***.com/questions/7999680/… 是的,这个问题我有答案。【参考方案3】:您可以使用delay()
等待一段时间或使用动画回调,将fadeOut
更改为animate
。
jQuery 使用 setTimeout 来设置动画和队列。
【讨论】:
【参考方案4】:与 20 年前的操作系统进行多任务处理的方式大致相同。没有线程,只有一个需要关注的事物列表和一个控制器,它会根据列表来关注事物。
单个线程只是遍历列表,一遍又一遍地为所有需要服务的事物提供服务。这里唯一的区别是有些事情有一个相关的等待期。它们在列表中,但仅在一段时间后才被标记为服务。它本质上是一个非常基本的调度程序实现。计算机上的内核做同样的事情。您的 CPU 只能同时执行几个程序,即使那样,也只能执行一些。操作系统内核必须以毫秒为单位决定谁得到关注(参见 jiffies)。 Javascript 的“内核”或运行时做同样的事情,但本质上就像它在只有一个内核的 CPU 上运行。
这里没有讨论中断队列之类的 CPU 可以处理的事情,我不确定 Javascript 有什么类似的,但在简单的层面上,我认为这是一个公平的表示。
【讨论】:
【参考方案5】:单线程与异步编程无关。 http://social.msdn.microsoft.com/Forums/uk/csharplanguage/thread/3de8670c-49ca-400f-a1dc-ce3a3619357d
如果您只有一个线程可以执行指令,则它不会/总是/正在执行。在那些空旷的地方,这是更多工作的机会。异步编程只是将工作分解为可重入的块,然后线程跳转到需要的地方。 (概念解释)
在这种情况下,您的问题可能更恰当:为什么这不是阻塞调用?在这种情况下,答案很明确,就是将 UI 动画与数据调用分开。整个 JS 环境不应阻塞 1 秒,同时使用小切片为元素设置动画,它可以检索或转换数据、为其他元素排队动画等。
【讨论】:
以上是关于jQuery如何拥有异步函数?的主要内容,如果未能解决你的问题,请参考以下文章