Javascript 以错误的顺序执行
Javascript executes in wrong order
我必须使用带有 select 元素的网站(票务系统),该元素当前包含 9994 个选项。这是不可更改的,必须按原样接受。
当我在该网站上处理工单时,我必须 select 来自该 select 的特定条目。我总共有大约 30 个条目可供选择。我不关心其他条目。
RegEx 过滤器所需的 30 个条目可以分为 3 个模式。
所以我决定使用 Greasemonkey+JQuery 来清理 select 元素,这样我就可以轻松快速地找到我要查找的条目。
过滤效果很好,但它需要时间(当然会......),所以我想显示一点 "please wait" div 作为叠加层,而过滤器是 运行 提供某种用户反馈。
在页面加载时创建叠加层:
$("body").append('<div id="pleaseWaitOverlay" style="position: fixed; top: 0; left: 0; bottom: 0; right: 0; background-color: rgb(255,255,255);">HALLO WELT</div>');
$("#pleaseWaitOverlay").hide();
//This is the select element with the "few" entries
fixedInReleaseElement = $('select[name=resolvedReleasePath]');
//Adding buttons to filter for one of the patterns are also added on page load
如果我按下其中一个过滤器按钮,将调用以下函数:
function filterFixedInReleaseList(filterFor) {
$("#pleaseWaitOverlay").show();
//$("#pleaseWaitOverlay").show().delay(500).show(); - or as hack without success...
var pattern;
//Based on "filterFor" parameter, the required pattern will be used.
// [MORE CODE]
fixedInReleaseElement.find("option").each(function() {
var currentOption = $(this);
if (pattern === "") {
currentOption.show();
}
else {
if (pattern.test(currentOption.text())) {
currentOption.show();
}
else {
currentOption.hide();
}
}
});
//$("#pleaseWaitOverlay").hide();
}
但不知何故,过滤将发生,然后将显示覆盖。
请注意:
- 目前,.hide() 行已被注释掉,因为执行这些行后弹出窗口根本不会显示(或更确切地说是看到)。
- .show().delay(500).show() 是一种破解它的尝试,但它绝对没有改变。
我也试过 fixedInReleaseElement.find("option").delay(1000).each() 但没有成功。我似乎延迟根本不起作用?
那么,这里的问题是什么?为什么滤镜执行后会出现叠加层?
完整的 Greasemonkey 脚本可以在这里找到:
http://pastebin.com/auafMSR1
一个浏览器选项卡只有一个线程,由 JavaScript 和 UI 更新共享。因此,如果您的 JavaScript 是 运行ning,则 UI 不会更新。
所以,这个:
function doSomethingLongWithOverlayWrongly() {
$x.show();
doSomethingLong();
$x.hide();
}
将$x
的适当属性设置为隐藏,然后做一些长的事情,然后将属性设置回来;当 doSomethingLongWithOverlayWrongly
(以及它未来的所有计算)最终退出并放弃对执行线程的控制时,浏览器将注意到某些属性已更改,并在必要时重新绘制(但事实并非如此,因为元素被设置为不可见,现在仍然设置为不可见)。
改为这样做:
function doSomethingLongWithOverlayCorrectly() {
$x.show();
setTimeout(function() {
doSomethingLong();
$x.hide();
}, 0);
}
这会将 $x
设置为隐藏,然后安排超时,然后退出。浏览器查看一下,发现重绘已按顺序进行,并显示您的叠加层。然后超时函数得到 运行,做一些很长的事情,并再次设置 $x
隐藏。当它退出时,浏览器会再看一眼,发现需要重新绘制,然后隐藏您的叠加层。
我必须使用带有 select 元素的网站(票务系统),该元素当前包含 9994 个选项。这是不可更改的,必须按原样接受。
当我在该网站上处理工单时,我必须 select 来自该 select 的特定条目。我总共有大约 30 个条目可供选择。我不关心其他条目。
RegEx 过滤器所需的 30 个条目可以分为 3 个模式。
所以我决定使用 Greasemonkey+JQuery 来清理 select 元素,这样我就可以轻松快速地找到我要查找的条目。
过滤效果很好,但它需要时间(当然会......),所以我想显示一点 "please wait" div 作为叠加层,而过滤器是 运行 提供某种用户反馈。
在页面加载时创建叠加层:
$("body").append('<div id="pleaseWaitOverlay" style="position: fixed; top: 0; left: 0; bottom: 0; right: 0; background-color: rgb(255,255,255);">HALLO WELT</div>');
$("#pleaseWaitOverlay").hide();
//This is the select element with the "few" entries
fixedInReleaseElement = $('select[name=resolvedReleasePath]');
//Adding buttons to filter for one of the patterns are also added on page load
如果我按下其中一个过滤器按钮,将调用以下函数:
function filterFixedInReleaseList(filterFor) {
$("#pleaseWaitOverlay").show();
//$("#pleaseWaitOverlay").show().delay(500).show(); - or as hack without success...
var pattern;
//Based on "filterFor" parameter, the required pattern will be used.
// [MORE CODE]
fixedInReleaseElement.find("option").each(function() {
var currentOption = $(this);
if (pattern === "") {
currentOption.show();
}
else {
if (pattern.test(currentOption.text())) {
currentOption.show();
}
else {
currentOption.hide();
}
}
});
//$("#pleaseWaitOverlay").hide();
}
但不知何故,过滤将发生,然后将显示覆盖。
请注意:
- 目前,.hide() 行已被注释掉,因为执行这些行后弹出窗口根本不会显示(或更确切地说是看到)。
- .show().delay(500).show() 是一种破解它的尝试,但它绝对没有改变。 我也试过 fixedInReleaseElement.find("option").delay(1000).each() 但没有成功。我似乎延迟根本不起作用?
那么,这里的问题是什么?为什么滤镜执行后会出现叠加层?
完整的 Greasemonkey 脚本可以在这里找到: http://pastebin.com/auafMSR1
一个浏览器选项卡只有一个线程,由 JavaScript 和 UI 更新共享。因此,如果您的 JavaScript 是 运行ning,则 UI 不会更新。
所以,这个:
function doSomethingLongWithOverlayWrongly() {
$x.show();
doSomethingLong();
$x.hide();
}
将$x
的适当属性设置为隐藏,然后做一些长的事情,然后将属性设置回来;当 doSomethingLongWithOverlayWrongly
(以及它未来的所有计算)最终退出并放弃对执行线程的控制时,浏览器将注意到某些属性已更改,并在必要时重新绘制(但事实并非如此,因为元素被设置为不可见,现在仍然设置为不可见)。
改为这样做:
function doSomethingLongWithOverlayCorrectly() {
$x.show();
setTimeout(function() {
doSomethingLong();
$x.hide();
}, 0);
}
这会将 $x
设置为隐藏,然后安排超时,然后退出。浏览器查看一下,发现重绘已按顺序进行,并显示您的叠加层。然后超时函数得到 运行,做一些很长的事情,并再次设置 $x
隐藏。当它退出时,浏览器会再看一眼,发现需要重新绘制,然后隐藏您的叠加层。