本文源于一个前两天同事的问题:
C#里面
while (condition) { Thread.Sleep(100);}// do something
这是一个比较奇怪的为问题,当是第一个出现在脑海里的是 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
新闻热点
疑难解答