Internet Explorer不按顺序执行Javascript

7
我正在开发一个web应用程序,需要在显示信息的同时进行一些后端处理。显然,这最适合使用AJAX,我正在使用它。但是,在开始AJAX请求之前,我通过Javascript进行了一些视觉上的更改。具体来说:
document.getElementById('calc').innerHTML = '计算中...'; document.getElementById('calc').disabled = true;
然后我通过AJAX调用一个servlet。
这在Firefox中运行良好。但是在Internet Explorer(版本8)中,视觉上的更改从未生效。应用程序只会停在那里一两分钟,直到完成AJAX处理。似乎AJAX代码在页面更改之前执行,但我不知道为什么会这样。
非常感谢任何帮助。
编辑:这是我最好的尝试,用简短、自包含、正确的示例来说明问题。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<script>
var inEdit = 0;
var calcCurrent = false; 
function recalc() {
var xmlhttp=new XMLHttpRequest();
if (xmlhttp==null)
{
  var tmp = "Your browser does not support XML! ";
  tmp += "Please contact your Technical Support division for information on how to upgrade.";
  alert(tmp);
}
else
{
  document.getElementById('calc').innerHTML = 'Calculating...';
  document.getElementById('calc').disabled = true;
  var url = "http://www.nzherald.co.nz/";
  xmlhttp.open("GET",url,false);
  xmlhttp.send(null);
  if (xmlhttp.responseText.indexOf("Success")>=0) {
    alert(xmlhttp.responseText);
  }
  else
    alert(xmlhttp.responseText);
  document.getElementById('calc').value = 'Recalculate';
  document.getElementById('calc').disabled = false;
}
}
</script>
</head>
<body>
<a id='calc' class='Button' href="javascript:recalc()" >Recalculate</a>
</body>
</html>

唯一的问题就是这个URL返回几乎是瞬间完成的。在我的应用程序中,它指向一个需要处理数据库约一分钟的页面,因此这个问题更加明显。

1
你的 calc 元素是什么?它可能不支持在 IE8 中使用 innerHTML - Phil
请确保在JavaScript中没有任何console.log语句,否则IE可能无法运行它们后面的代码。如果这是问题,您可以在运行时打开开发人员工具,这样它就会运行。 - Ryan
3
希望提供更多的代码。 - j08691
1
请提供一个简短、自包含、正确(可编译)的示例 - Jared Farrish
"calc" 是一个锚点 <a> 元素,我相当确定它支持 innerHTML。此外,innerHTML 最终会发生变化,只是需要一些时间。 - enjiner
http://jsfiddle.net/wilmoore/grMKj/ - Wil Moore III
3个回答

1

这两行代码非常简单。有两件事情需要注意:

  1. 您是否为另一个元素定义了ID。请通过在“查看源代码”中执行Ctrl+F来确认calc未在页面的其他位置使用。
  2. 验证您的HTML。确保您没有遗漏任何闭合标签或属性中的引号。

感谢epignosisx的建议。我检查了这两个问题。验证后发现有很多不符合规范的HTML,包括缺少标签。不幸的是,我描述的问题仍然存在,但能够识别出验证问题是好的!再次感谢。 - enjiner

1

您正在将“false”传递给xmlhttp.open()调用的async参数。因为自从您设置了calc元素的innerHTML属性以来,堆栈尚未展开,IE还没有机会重新绘制屏幕。

您有几个选项。

  1. 重构您的代码,使您通过回调通知异步进行ajax调用并获取结果。

  2. 或者...在calc上设置innerHTML属性,然后使用延迟为0和回调函数调用setTimeout,该回调函数编写为按照您现在所拥有的方式调用xmlhttp.open。这将允许堆栈展开,IE将重新绘制DOM更改,然后执行您的ajax调用。下面是您的代码的一个混合版本,以演示我所说的内容。

以下是一些混乱的代码,演示#2。

var xmlhttp;

function recalc() {
    xmlhttp=new XMLHttpRequest();
    if (xmlhttp==null)
    {
      var tmp = "Your browser does not support XML! ";
      tmp += "Please contact your Technical Support division for information on how to upgrade.";
      alert(tmp);
    }
    else
    {
      document.getElementById('calc').innerHTML = 'Calculating...';
      document.getElementById('calc').disabled = true;
      setTimeout(recalc_start, 0);
    }
}

function recalc_start() {
  var url = "http://www.nzherald.co.nz/";

  xmlhttp.open("GET",url,false);
  xmlhttp.send(null);
  if (xmlhttp.responseText.indexOf("Success")>=0) {
    alert(xmlhttp.responseText);
  }
  else {
    alert(xmlhttp.responseText);
  }
  document.getElementById('calc').value = 'Recalculate';
  document.getElementById('calc').disabled = false;
}

如果上面的代码片段不起作用,那么尝试将超时时间从“0”更改为“1”或更高的值。 - selbie
太棒了!这个选项(使用超时)完美地解决了我的问题。很高兴知道为什么会发生这种情况。非常感谢。 - enjiner
@enjiner - 很高兴它起作用了。理想情况下,您应该选择选项#1。否则,ajax请求中的非常长的延迟可能会使您的网页“冻结”(或至少其他JavaScript代码无法运行),直到ajax调用完成。 - selbie

0

我假设这是一个 <input id='calc' type='text' /> 元素:

document.getElementById('calc').value = 'Calculating...';
document.getElementById('calc').setAttribute('disabled','disabled');

为了获得最佳的多浏览器兼容性,请尝试使用jQuery:

$("#calc").val('Calculating...').attr('disabled','disabled');  

无法想象有哪个浏览器会对第一个示例有问题。jQuery 在这里没有做任何有用的事情。 - Phil
@ron - 对于“最佳浏览器兼容性”,只需直接设置属性,无需使用setAttribtue或jQuery(或其混乱的attr函数)。 - RobG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接