Javascript方法有效且不起作用

时间:2017-03-02 17:18:35

标签: javascript

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

基本上,我有一个旋转加载器元素,应该在我的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();方法直接从控制台运行。

我无法弄清楚我错过了什么。

1 个答案:

答案 0 :(得分:1)

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

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

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