innerHTML不可信:不总是同步执行 [英] innerHTML can't be trusted: Does not always execute synchronously

查看:283
本文介绍了innerHTML不可信:不总是同步执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要查看问题,请参阅此jsbin 。单击该按钮会触发 buttonHandler(),如下所示:

To see the problem in action, see this jsbin. Clicking on the button triggers the buttonHandler(), which looks like this:

function buttonHandler() {
  var elm = document.getElementById("progress");
  elm.innerHTML = "thinking";
  longPrimeCalc();
}

您可能希望此代码将div的文本更改为思考 ,然后运行 longPrimeCalc(),这是一个需要几秒钟才能完成的算术函数。然而,这不是发生的事情。相反,longPrimeCalc首先完成,然后文本在运行完毕后更新为思考,就好像两行代码的顺序相反。

You would expect that this code changes the text of the div to "thinking", and then runs longPrimeCalc(), an arithmetic function that takes a few seconds to complete. However, this is not what happens. Instead, "longPrimeCalc" completes first, and then the text is updated to "thinking" after it's done running, as if the order of the two lines of code were reversed.

看起来浏览器不会同步运行innerHTML代码,而是为它创建一个自己休闲执行的新线程。

It appears that the browser does not run "innerHTML" code synchronously, but instead creates a new thread for it that executes at its own leisure.

我的问题:


  1. 导致此行为的根本原因是什么?

  2. 如何获取浏览器?按照我期望的方式行事,即强制它在执行 longPrimeCalc()之前更新innerHTML?

  1. What is happening under the hood that is leading to this behavior?
  2. How can I get the browser to behave the way I would expect, that is, force it to update the "innerHTML" before it executes "longPrimeCalc()"?

我在最新版本的chrome中对此进行了测试。

I tested this in the latest version of chrome.

推荐答案


  1. 我认为它的工作方式是首先完成当前运行的代码,然后完成所有页面更新。在这种情况下,调用 longPrimeCalc 会导致执行更多代码,并且只有在完成后才会更改页面更新。

  1. I think the way it works is that the currently running code completes first, then all the page updates are done. In this case, calling longPrimeCalc causes more code to be executed, and only when it is done does the page update change.

要解决此问题,您必须终止当前正在运行的代码,然后在另一个上下文中开始计算。你可以用 setTimeout 来做到这一点。我不确定除此之外还有其他任何方式。

To fix this you have to have the currently running code terminate, then start the calculation in another context. You can do that with setTimeout. I'm not sure if there's any other way besides that.

这是一个 jsfiddle 显示行为。您不必将回调传递给 longPrimeCalc ,您只需创建另一个函数,它可以使用返回值执行您想要的操作。基本上,您希望将计算推迟到执行的另一个线程。以这种方式编写代码可以明显地显示您正在做什么(再次更新以使其更好):

Here is a jsfiddle showing the behavior. You don't have to pass a callback to longPrimeCalc, you just have to create another function which does what you want with the return value. Essentially you want to defer the calculation to another "thread" of execution. Writing the code this way makes it obvious what you're doing (Updated again to make it potentially nicer):

function defer(f, callback) {
  var proc = function() {
    result = f();
    if (callback) {
      callback(result);
    }
  }
  setTimeout(proc, 50);
}

function buttonHandler() {
  var elm = document.getElementById("progress");
  elm.innerHTML = "thinking...";
  defer(longPrimeCalc, function (isPrime) {
    if (isPrime) {
      elm.innerHTML = "It was a prime!";
    }
    else {
      elm.innerHTML = "It was not a prime =(";
    }
  });
}

这篇关于innerHTML不可信:不总是同步执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆