暂停JavaScript执行而不锁定浏览器

时间:2010-01-19 21:48:23

标签: javascript execution

您是否能够在不锁定浏览器的情况下暂停JavaScript执行?通常停止执行的方式是执行无限while() - 循环,但在FireFox的情况下,它会锁定浏览器,直到循环结束。

你对此有何看法?


我试图覆盖window.confirm()以使用HTML实现我自己的对话框。我这样做,所以我不必更改现有代码(这是一个相当大的代码库)。

我需要能够暂停执行以允许用户输入;反过来返回一个像标准确认函数那样的布尔值:

if (confirm("..."))
{
    // user pressed "OK"
}
else
{
    // user pressed "Cancel"
}



更新

据我所知;使用setTimeout()setInterval()无法完成此操作,因为这些函数会异步执行为它们提供的代码。

7 个答案:

答案 0 :(得分:9)

confirm() prompt()alert()是特殊功能 - 它们将JavaScript沙箱调用到浏览器中,浏览器暂停JavaScript执行。你不能做同样的事情,因为你需要在JavaScript中构建你的功能。

我不认为如果没有按照以下方式进行重组,就有一个很好的方法可以放弃替换:

myconfirmfunction(function() {
   /* OK callback */
}, function() {
   /* cancel callback */
});

答案 1 :(得分:7)

您无法在JavaScript中停止事件线程,因此您必须解决此问题,通常是使用回调函数。这些函数稍后运行,但可以像JavaScript中的任何其他对象一样传递。您可能从AJAX编程中熟悉它们。所以,例如:

doSomeThing();
var result = confirm("some importart question");
doSomeThingElse(result);

将转换为:

doSomeThing();
customConfirm("some importart question", function(result){
  doSomeThingElse(result);
});

其中customConfirm现在接受一个问题并将结果传递给它作为参数的函数。如果使用按钮实现DOM对话框,则将事件侦听器连接到OK和CANCEL按钮,并在用户单击其中一个时调用回调函数。

答案 2 :(得分:7)

使用回调或使您的代码仅限Firefox。在支持JavaScript 1.7及更高版本的Firefox中,您可以使用yield语句来模拟所需的效果。我为此创建了一个名为async.js的库。 async.js的标准库包含一个confirm方法,可以这样使用:

if (yield to.confirm("...")) {
  // user pressed OK
} else {
  // user pressed Cancel
}

答案 3 :(得分:3)

JavaScript语言的扩展名为StratifiedJS。它可以在每个浏览器中运行,它允许您这样做:停止一行JavaScript代码而不冻结浏览器。

您可以启用分层JavaScript,例如在你的网页上加入Oni Apollo(http://onilabs.com/docs),如:

<script src="http://code.onilabs.com/latest/oni-apollo.js"></script>
<script type="text/sjs"> your StratifiedJS code here </script>

您的代码如下所示:

var dom = require("dom");
displayYourHtmlDialog();
waitfor {
  dom.waitforEvent("okbutton", "click");
  // do something when the user pressed OK
}
or {
  dom.waitforEvent("cancelbutton", "click");
}
hideYourHtmlDialog();
// go on with your application

答案 4 :(得分:2)

通常停止执行的方式几乎不应该是无限循环。

将您的工作分解为使用SetTimeout

调用的部分

改变这个:

  DoSomeWork();
  Wait(1000);
  var a = DoSomeMoreWork();
  Wait(1000);
  DoEvenMoreWork(a);

到此:

 DoSomeWork();
 setTimeout(function() {
    var a = DoSomeMoreWork();
    setTimeout(function() { 
        DoEvenMoreWork(a);
    }, 1000);
 }, 1000);

答案 5 :(得分:1)

我认为没有办法在你自己的JavaScript中合理地重新创建confirm()或prompt()的功能。它们是作为对本机浏览器库的调用实现的意义上的“特殊”。你不能在JavaScript中真正做那种模式对话。

我已经看过各种UI库,它们通过在页面顶部放置一个元素来模拟效果。就像一个模态对话框,但这些是使用异步回调实现的。

您必须修改现有的库,而不是替换window.confirm。

答案 6 :(得分:0)

我尝试使用this的紧密循环。我需要减慢本机事件(AFAIK是同步等待的唯一用例,无法异步重新构建)。有很多示例循环声称不会锁定浏览器;但是它们都没有为我工作(浏览器没有锁定,但它们阻止它做我最初等待的事情),所以我放弃了这个想法。

接下来我尝试this - 存储和重放事件,这似乎也不可能跨浏览器。但是,根据事件的情况以及您需要的灵活性,您可以近距离接触。

最后我放弃了,感觉好多了;我找到了一种方法来使我的代码工作,而不必减慢本机事件的速度。