6

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

你对此有何看法?


我正在尝试覆盖window.confirm()以使用 HTML 实现我自己的对话框。我这样做是为了不必更改现有代码(这是一个非常大的代码库)。

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

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



更新

据我所知; 这不能使用setTimeout()setInterval()因为这些函数异步执行给它们的代码来完成。

4

7 回答 7

9

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

我不认为有一个很好的方法可以在不进行一些重组的情况下进行替换:

myconfirmfunction(function() {
   /* OK callback */
}, function() {
   /* cancel callback */
});
于 2010-01-19T21:53:45.057 回答
7

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

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

将被转换为:

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

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

于 2010-01-19T22:08:51.620 回答
7

要么使用回调,要么让你的代码只支持 Firefox。在支持 JavaScript 1.7 及更高版本的 Firefox 中,您可以使用 yield 语句来模拟您想要的效果。为此,我创建了一个名为async.js的库。async.js 的标准库包含一个确认方法,可以这样使用:

if (yield to.confirm("...")) {
  // user pressed OK
} else {
  // user pressed Cancel
}
于 2010-01-20T02:16:03.657 回答
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
于 2010-09-23T10:54:23.220 回答
2

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

将您的工作分解为您使用 SetTimeout 调用的部分

改变这个:

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

对此:

 DoSomeWork();
 setTimeout(function() {
    var a = DoSomeMoreWork();
    setTimeout(function() { 
        DoEvenMoreWork(a);
    }, 1000);
 }, 1000);
于 2010-01-19T21:54:16.630 回答
1

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

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

您将不得不修改现有库,而不是替换 window.confirm。

于 2010-01-20T02:08:13.207 回答
0

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

接下来我尝试了这个- 存储和重播事件,这似乎也是不可能的跨浏览器。但是,根据事件和您需要的灵活性,您可以接近。

最后我放弃了,感觉好多了;我找到了一种让我的代码工作的方法,而无需减慢原生事件的速度。

于 2010-08-01T04:16:56.510 回答