得有段时间没好好写篇博客了,这次我们从一个题目开始吧。
首先我给大家出一道题目,大家可以先思考一下,再往下看。
题目是:请用JavaScript重写confirm方法,实现和confirm同样的功能。
乍一看可能感觉很简单,定义一个confirm方法覆盖window对象原生的 confirm方法,在方法里用div画一个弹框,参数中传入两个回调方法,当用户点击“确定”或者“取消”的时候分别调用相应的回调方法,如下:
confirm("确定吗?",callBack1,callBack2);
但是这样和原来的confirm()方法是不一样的,原来的confirm()方法只有一个参数,只传入要显示的消息,并且用户点击按钮之前线程是暂停的,只有当用户点击确定或者取消后,接下来的代码才会继续执行,并不需要回调方法,这样业务逻辑更清晰有条理。
如上面两图,原生的confirm方法在各个浏览器样式不同,但功能相同,即都能够暂停程序执行,直到用户点击了按钮。
那么我们能否用纯JavaScript做出一个样式不同但功能相同的confirm方法来覆盖原生的confirm方法呢,答案是可以的,思路就是暂停程序的执行,是暂停而不是堵塞JavaScript线程,因为一旦JavaScript线程被阻塞,dom渲染的线程也会被挂起,从而导致用户无法点击弹框出现的按钮,所以像while(true){...}这种写法是不可取的,JavaScript不像c或c++那样,JavaScript出现这种死循环很快会堆栈溢出,程序就挡掉了。那么如何实现代码的暂停呢,es6中新出了await关键字,await简单来讲就是让程序同步而不是以异步的方式执行,字面意思就是等待,等着程序执行完再进行下一步,await只能用在异步的方法里面,既带有async标记的function。我今天跟大家分享的实现程序暂停的方法就是通过await实现的。
首先,我们可以构造一个同步函数, waitUserClick()
this.WAIT_USER_CLICK=true;//等待用户点击的状态
this.SYS_USER_FEED_BACK=true;//用户点击回馈缓存
/**
* 等待用户点击状态方法,每100毫秒询问一次
* @param {[type]} val [description]
* @return {[type]} [description]
*/
this.waitUserClick=function(){
return new Promise(function(resolve){
setTimeout(function(){
resolve();
},100);
});
}
waitUserClick()相当于一个同步的方法,执行这个函数结束需要等待100毫秒,这个等待多长时间我们可以随意调节,这个函数的作用就是让你等待100毫秒,其他的什么都不干,那么有个这个等待函数了,我们可以接下来实现一个while循环来监听用户有没有点击按钮。