开发者

Halt JavaScript execution without locking up the browser

Are you able to halt JavaScript execution without locking up the browser? The way you would normally halt execution is to do an infinite while()-loop, but in the case of FireFox, it locks up the brow开发者_如何学Goser until the loop has ended.

What's your take on this?

I am trying to override window.confirm() to implement my own dialog using HTML. I am doing this so I don't have to change existing code (it's a pretty big code-base).

I need to be able to halt execution to allow user-input; to in turn return a boolean like the standard confirm function does:

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

Update

To my knowledge; this cannot be done using setTimeout() or setInterval() since these functions execute the code thats given to them asynchronously.


confirm() prompt() and alert() are special functions--they call out of the JavaScript sandbox into the browser, and the browser suspends JavaScript execution. You can't do the same thing, since you need to build your functionality into JavaScript.

I don't think there's a great way to drop in a replacement without doing some restructuring along the lines of:

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


Either use callbacks or make your code Firefox-only. In Firefox with support for JavaScript 1.7 and higher, you can use the yield statement to simulate your desired effect. I have created a library for this purpose called async.js. The standard library for async.js includes a confirm method, which can be used as such:

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


You cannot stop the event thread in JavaScript, so instead you have to work around the problem, usually by using callback functions. These are functions that are run at a later time, but can be passed around like any other object in JavaScript. You might be familiar with them from AJAX programming. So, for example:

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

Would be converted into:

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

where customConfirm now takes a question and passes the result to the function it takes as an argument. If you implement a DOM dialog with a button, then connect an event listener to the OK and CANCEL buttons, and call the callback function when the user clicks on one of them.


There is an extension to the JavaScript language called StratifiedJS. It runs in every browser, and it allows you to do just that: halting one line of JavaScript code without freezing the browser.

You can enable Stratified JavaScript e.g. by including Oni Apollo ( http://onilabs.com/docs ) in your webpage like:

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

Your code would look like this:

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


the way you normally halt execution should hardly ever be an infinite while loop.

break up your work into parts, that you call with SetTimeout

change this:

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

to this:

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


I don't think there's any way to reasonably re-create the functionality of confirm() or prompt() in your own JavaScript. They're "special" in the sense of being implemented as calls into the native browser library. You can't really do a modal dialog of that sort in JavaScript.

I have seen various UI libraries that simulate the effect by putting an element on top of the page, that looks & acts like a modal dialog, but those are implemented using async callbacks.

You will have to modify the existing library, rather than replacing window.confirm.


I tried using tight looping for this. I needed to slow down a native event (which AFAIK is the only use case for a synchronous wait that can't be re-architected asynchronously). There are lots of example loops out there that claim not to lock up the browser; but none of them worked for me (the browser didn't lock up, but they prevented it from doing the thing I was waiting for in the first place), so I abandoned the idea.

Next I tried this - storing and replaying the event, which seems to be impossible cross-browser too. However depending on the event and how flexible you need to be, you can get close.

In the end I gave up, and feel much better for it; I found a way to make my code work without having to slow down the native event at all.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜