浏览器的“sleep”
本文源于一个前两天同事的问题:
C#里面
while (condition) { Thread.Sleep(100); } // do something在javascript里面怎么实现比较好
这是一个比较奇怪的为问题,当是第一个出现在脑海里的是 setTimeout,也就是如下代码(setInterval也是类似的实现):
不过这样有问题,这是一个异步的回调,同事需要的是浏览器有 blocking 的效果,当是没有太多的考虑就觉得没办法实现了。
setTimeout(function () { if (condition) { setTimeout(arguments.callee, 100); return; } // do something }, 100);
今天再次想起那个问题,在园子里找了一下,发现有各种实现方式,不过实现方式都实在不敢恭维~~
总结了浏览器有 blocking 效果的几个方式:
1. 各种原生的消息弹出框,比如 alert,confirm,prompt
2. 模式窗体,showModalDialog
3. XMLHttpRequest 的同步请求
4. 看到园子里有人直接while(condition){}, 汗~~
而第3点就是这个问题的突破点,XHR的open方法有一个指定是否为同步方式的参数,详见MDN
void open( DOMString method, DOMString url, optional boolean async, optional DOMString user, optional DOMString password );
于是乎实现变得简单了,这里需要有一个真实的地址共供XHR使用,
public class HomeController : Controller { public ActionResult Wait(int sleep) { System.Threading.Thread.Sleep(sleep); return new EmptyResult(); } }
然后是客户端的js代码:(注意需要设置timeout,以增加计时的准确性)
function sleep(time, done) { var xhr = new XMLHttpRequest(); xhr.timeout = time; xhr.onerror = done; xhr.onload = done; xhr.open('GET', '/Home/Wait?sleep=' + time, false); xhr.send(''); }
或是用jquery更方便:
function sleep(time, done) { $.ajax({ async: false, url: '/Home/Wait?sleep=' + time, timeout: time, error: done, success: done }); }
最后这样使用:
sleep(100, function () { if (condition) { sleep(100, arguments.callee); return; } // do something });
这算是个比较另类的实现方式,不知道谁有更好的实现,请留言赐教!谢谢了!
参考:
https://developer.mozilla.org/zh-CN/docs/DOM/XMLHttpRequest
浏览器没那么聪明!