gpt4 book ai didi

javascript - 单线程JavaScript下的动画

转载 作者:数据小太阳 更新时间:2023-10-29 04:24:18 24 4
gpt4 key购买 nike

JavaScript是一种单线程语言,因此它一次执行一个命令。正在通过浏览器管理的 Web API (用于事件处理的DOM,用于AJAX调用的XMLHttpRequest,用于setTimeout的WindowTimers)和事件队列来实现异步编程。到现在为止还挺好!现在考虑以下非常简单的代码:

$('#mybox').hide(17000);
console.log('Previous command has not yet terminated!');
...

有人可以向我解释以上内容的潜在机制吗?由于.hide()尚未完成(动画持续17秒),并且JS引擎正在处理它,并且它能够一次执行一个命令,因此它将转到下一行并继续运行剩下的代码?

如果您的回答是动画创建了 promise , 的问题仍然相同:JavaScript如何同时处理多个事情(执行动画本身,在出现 promise 的情况下观看动画队列并继续执行以下代码跟随...)。

而且,我无法解释如果 promise 必须在解决或拒绝父deferred对象(直到代码被解析或拒绝)之前jQuery的 promise 如何工作 ,这意味着代码执行,同时执行其余代码。单线程方法怎么可能?我了解AJAX调用没有问题,因为我知道它们已从JS引擎中删除了...

最佳答案

tl; dr; ,在没有外部帮助的情况下,在严格的单线程环境中是不可能的。

我想我了解您的问题。让我们解决一些问题:

JavaScript始终是同步的

语言规范中未定义异步API。像Array.prototype.mapString.fromCharCode这样的所有功能始终同步运行*。

代码将始终运行到完成。在被return,隐式return(到达代码的末尾)或throw(突然)终止之前,代码不会停止运行。

a();
b();
c();
d(); // the order of these functions executed is always a, b, c, d and nothing else will
// happen until all of them finish executing

JavaScript驻留在平台内

JavaScript语言定义了一个称为 host environment的概念:

In this way, the existing system is said to provide a host environment of objects and facilities, which completes the capabilities of the scripting language.



在浏览器中运行JavaScript的主机环境称为 DOM或文档对象模型。它指定浏览器窗口如何与JavaScript语言进行交互。例如,在NodeJS中,主机环境是完全不同的。

尽管所有JavaScript对象和函数都同步运行以完成操作,但宿主环境可能会公开自己的功能,而这些功能不一定是在JavaScript中定义的。它们没有标准JavaScript代码所具有的相同限制,并且可能定义了不同的行为-例如 document.getElementsByClassName的结果是实时DOM NodeList ,它的行为与普通JavaScript代码有很大不同:
var els = document.getElementsByClassName("foo"); 
var n = document.createElement("div");
n.className = "foo";
document.body.appendChild(n);
els.length; // this increased in 1, it keeps track of the elements on the page
// it behaves differently from a JavaScript array for example.

这些主机功能中的某些功能必须执行I/O操作(如计划计时器),执行网络请求或执行文件访问。像所有其他API一样,这些API必须运行完整。这些API由宿主平台提供-它们调用您的代码不具备的功能-通常(但不一定)它们是用C++编写的,并使用线程和操作系统工具来并行和并行运行事物。这种并发可以仅仅是后台工作(如安排计时器)或实际的并行性(如 WebWorkers-也是DOM的一部分,而不是JavaScript的一部分)。

因此,当您在DOM上调用诸如setTimeout之类的 Action ,或应用导致CSS动画的类时,它并不会受到代码所具有的相同要求的约束。它可以使用线程或操作系统 async io

当您执行以下操作时:
setTimeout(function() {
console.log("World");
});
console.log("Hello");

实际发生的是:
  • 主机函数setTimeout通过类型为function的参数进行调用。它将函数插入queue in the host environment
  • console.log("Hello")是同步执行的。
  • 所有其他同步代码都运行(注意,setTimeout调用在此是完全同步的)。
  • JavaScript已完成运行-控制权已转移到主机环境。
  • 主机环境注意到它在计时器队列中有东西,并且已经经过了足够的时间,因此它调用其参数(函数)-console.log("World")被执行。
  • 函数中的所有其他代码均同步运行。
  • 将控制权交还给主机环境(平台)。
  • 主机环境中还发生了其他事情(鼠标单击,AJAX请求返回,计时器触发)。主机环境调用用户传递给这些操作的处理程序。
  • 再次所有JavaScript均同步运行。
  • 等等,依此类推...

  • 您的具体情况
    $('#mybox').hide(17000);
    console.log('Previous command has not yet terminated!');

    这里的代码是同步运行的。前面的命令已终止,但是实际上并没有做太多-而是在平台a(在 .hide(17000)中)安排了回调,然后再次执行 console.log-所有JavaScirpt代码始终始终同步运行。

    那就是-hide只执行很少的工作,并运行几毫秒,然后安排更多的工作在以后进行。它不会运行17秒钟。

    现在,hide的实现如下所示:
    function hide(element, howLong) {
    var o = 16 / howLong; // calculate how much opacity to reduce each time
    // ask the host environment to call us every 16ms
    var t = setInterval(function
    // make the element a little more transparent
    element.style.opacity = (parseInt(element.style.opacity) || 1) - o;
    if(parseInt(element.style.opacity) < o) { // last step
    clearInterval(t); // ask the platform to stop calling us
    o.style.display = "none"; // mark the element as hidden
    }
    ,16);
    }

    因此,基本上我们的代码是单线程的-它要求平台每秒调用60次,并使该元素每次不那么可见。一切总是可以完成的,但除了第一个代码执行,平台代码(主机环境)正在调用我们的代码,反之亦然。

    因此,对于您的问题的实际直接答案是,与您发出AJAX请求时类似,计算时间从代码中“夺走了”。要直接回答:

    没有外部帮助,在单线程环境中是不可能的。

    外部是使用线程或操作系统异步功能的封闭系统-我们的主机环境。没有纯标准的ECMAScript,就无法做到这一点。

    *在ES2015中包含了promise,该语言将任务委派回平台(主机环境)-但这是一个异常(exception)。

    关于javascript - 单线程JavaScript下的动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35362458/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com