【问题标题】:Javascript method works and doesn't workJavascript方法有效且无效
【发布时间】:2017-03-12 10:38:23
【问题描述】:

我什至很难问这个问题,因为我不明白发生了什么。

基本上,我有一个旋转加载器元素,应该在我的 javascript 运行时显示。在 javascript 结束时,应关闭加载程序,并应显示一个模式,其中包含从数据库查询的数据。问题是加载程序永远不会显示。在创建模式之前查询运行大约需要 1 到 2 秒的等待时间。

function includeConnectionJS() {
    if (!(typeof sforce === "object")) {
        var connectionJS = document.createElement('script');
        var documentHead = document.getElementsByTagName('head')[0];

        connectionJS.src = '/soap/ajax/38.0/connection.js';
        connectionJS.setAttribute('onload', 'createLoader();createModal();');
        documentHead.appendChild(connectionJS);
    } else {
        createLoader();
        // Checks to see if the loader element exists. If it does not, create the element and than toggle it to display it.
        // If the element already exists, display the modal
        createModal();
        // Checks to see if the modal element exists, if it does not, create the element and than turn off the loader and display the modal.
        // If the element already exists, turn off the loader and display the modal
    }
}

我将 console.logs 放在我的方法中,我可以清楚地看到该方法正在被调用,if 语句全部通过,并且元素的可见性在正确的时间更改为正确的值。一切似乎都暗示它应该可以工作,但该元素从未真正显示出来。

我可以通过将 createModal 调用更改为如下所示来显示它:

setTimeout(function(){createModal()}, 100); // Most values for delay worked.

我不想为了显示加载器的效果而人为地延迟。

我主要关心的是 createModal 方法调用数据库。这些会导致 javascript 执行延迟(我同步调用它们,而不是异步调用它们)。我可以清楚地看到在查询之前加载程序显示被设置为“阻塞”,观察所有查询调用并返回,并看到加载程序的显示以正确的顺序变回“无”。不仅如此,如果我调用 createLoader();直接从控制台方法,它的工作原理。

我只是想不通我错过了什么。

【问题讨论】:

  • 您描述的所有内容,从正确的顺序到setTimeout“修复”问题听起来就像createModal() 过早关闭加载程序。如果不查看您的其余代码,我们将无法为您提供帮助。黑暗中的一枪:如果你想告诉 JS 在 B 发生后执行 A(),你需要传递 function() { A(); },而不是 A();
  • @ChrisG 不,Javascript 的本质是阻止对 UI 的更新,直到正在执行的代码完全完成。此外,javascript 在单线程中按顺序执行,因此 A 将始终在 B 之后执行 B(); A();AB 完成之前永远无法启动

标签: javascript


【解决方案1】:

使用同步 Javascript 调用,您会阻塞在事件循环 https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop#Run-to-completion 中排队的 UI 和其他功能。重要的是要记住 Javascript 代码在单线程中执行。所以没有代码可以并行执行,其他一切都必须等到当前任务完成。实际上,这意味着您希望您的函数尽快完成它们的工作,以便其他操作(UI 更新、键盘/鼠标事件等、超时或异步回调等)可以执行。它们都必须等到您通过完成当前代码块将控制权交还给引擎。

setTimeout 之所以有效,是因为它将长时间运行的createModal 函数添加到事件队列中,以便在将来的某个时间执行(即使设置为 0ms - 它也不能保证立即执行,它只是在第一次有机会时说你可以某时经过 0 毫秒后。如果您有一个长时间运行的函数,实际上可能是 10 秒后)。这样做可以让调用函数快速完成,并且 UI 现在能够应用任何更新。现在,当 javascript 引擎准备好运行进一步的代码时,它将查找事件循环中记录的下一个代码块。这一次当它运行createModal 时,它将再次阻止对 UI 等的更新,处理鼠标和键盘事件等,但现在 UI 有机会更新,您将启动您的微调器。

因此选择是:在您的函数中使用异步调用以使其快速完成,或者如果这不可能,则在 UI 更新后继续使用 setTimeout() 将长时间运行的任务排队。

【讨论】:

    猜你喜欢
    • 2019-03-31
    • 1970-01-01
    • 2020-05-22
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 2015-04-07
    相关资源
    最近更新 更多