//第一种,使用while循环
function sleep(delay) {
var start = (new Date()).getTime();
while((new Date()).getTime() - start < delay) {
continue;
}
}
//或者使用for循环
function sleep(delay) {
for(var t = Date.now(); Date.now() - t <= d;);
}

这种实现方式是利用一个伪死循环阻塞主线程。因为JS是单线程的。所以通过这种方式可以实现真正意义上的sleep()。

Js阻塞机制,跟Js引擎的单线程处理方式有关,每个window一个JS线程。所谓单线程,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码。

由于浏览器是事件驱动的(Event driven),因此浏览器中很多行为是异步(Asynchronized)的,很容易有事件被同时或者连续触发。当异步事件发生时,会创建事件并放入执 行队列中,等待当前代码执行完成之后再执行这些代码,如鼠标点击事件发生、定时器触发事件发生、XMLHttpRequest完成回调这些事件,都会被放 入执行队列中等待。

关于Js的阻塞机制,可以看下面一段代码,一般,我们会认为,这段代码会log出来0,1,2

for(var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, (i + 1) * 1000);
}

而实际上,这段代码log出来的结果是 3,3,3。这是js新手很容易遇到的问题,具体原因就是因为for循环的阻塞机制。在上面的代码中,setTimeout这个定时器需要等待for循环 执行完成,而for循环执行完成了之后,i已经为3了,此时才开始执行setTimeout,因此console.log(i)会是3。

至于为什么i会是3,请回顾一下for循环的执行顺序,当i为2的时候,满足循环条件,执行代码块,然后i++,此时i为3,不满足循环条件,不执行代码块,循环停止。

对于for循环,记住,是在不满足条件的情况下停止循环,对于以上代码,可以看出,i=3的时候才不满足。

怎么解决事件阻塞

其实,阻塞作为js引擎的处理方式,我们最好不要想着解决“阻塞”,而是让我们想执行的代码,插入到“主线程”中。这么说比较不易理解,还是以上面的代码为例,直接上代码好了

for(var i = 0; i < 3; i++) {
(function(i) {
setTimeout(function() {
console.log(i);
}, (i + 1) * 1000);
})(i)
}

再上面的代码中,我们加了一个立即执行的匿名函数,并且将for循环的i作为实参传入进去。这样,setTimeout就会被立即执行,而不会等待(这里不太了解细节,就不多说了,大概猜测为新开了一个临时的线程,立即执行匿名函数,然后再立即切换回来)。

本文主要在说明如何解决这一类问题,对于底层原理,还待继续挖掘。

注意:html5支持Web worker功能,可以写多线程

JS实现停留几秒sleep,Js中for循环的阻塞机制,setTimeout延迟执行的更多相关文章

  1. Js中for循环的阻塞机制

    Js阻塞机制,跟Js引擎的单线程处理方式有关,每个window一个JS线程.所谓单线程,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码. 由于浏览器是事件驱动的(Event driven) ...

  2. Android中的Handler,以及用Handler延迟执行

    项目中遇到一个情况,先生成文件再上传:但有时候发出指令后上传会不成功,需要再发一次指令方能上传. 猜想是由于文件还没生成就执行「上传」指令了.想到要延时.Android中单纯用currentThrea ...

  3. iOS中延迟执行和取消的几种方式

    公用延迟执行的方法: - (void)delayMethod { NSLog(@"delayMethodEnd"); } 方法一.performSelector 方法 1.延迟执行 ...

  4. C#中Linq延迟执行问题

    本文来自:http://msdn.microsoft.com/zh-cn/library/bb399393(v=vs.110).aspx http://www.cnblogs.com/zhanglin ...

  5. js弹框3秒后自动消失

    开发中有时候会需要最出弹框后,过几秒自动消失的效果,下面给大家分享一下我自己做的一个小案例. 案例中的弹框使用的是bootstrap里面的模态框,实现自动消失则用的是js中的setInterval方法 ...

  6. 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)

    首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...

  7. dynamic-css 动态 CSS 库,使得你可以借助 MVVM 模式动态生成和更新 css,从 js 事件和 css 选择器的苦海中脱离出来

    dynamic-css 使得你可以借助 MVVM 模式动态生成和更新 css,从而将本插件到来之前,打散.嵌套在 js 中的修改样式的代码剥离出来.比如你要做元素跟随鼠标移动,或者根据滚动条位置的变化 ...

  8. Js控制显示、隐藏文本框中的密码

    Js控制显示.隐藏文本框中的密码,也可称为是一款小型的JavaScript星号密码破解器,点击会显示出密码类型的文本框中的真实信息,再次点击则还原,程序 主要是获取HTML元素对象,然后强制更改元素属 ...

  9. js中的延迟执行和定时执行

    在js中,延迟执行函数有两种,setTimeout和setInterval,用法如下: function testFunction(){Console.log('hovertree.com');} s ...

随机推荐

  1. cesium 学习(六) 坐标转换

    cesium 学习(六) 坐标转换 一.前言 在场景中,不管是二维还好还是三维也罢,只要涉及到空间概念都会提到坐标,坐标是让我们理解位置的一个非常有效的东西.有了坐标,我们能很快的确定位置相关关系,但 ...

  2. 《VR入门系列教程》之21---使用Unity开发GearVR应用

    使用Unity开发GearVR应用     上一章我们介绍了如何运用Unity3D开发Oculus Rift应用,当然,这个便宜且强大的游戏引擎也可以用于GearVR的应用开发,这时我们需要用到Ocu ...

  3. mpvue的使用,包含axios、router的集成等完美结合小程序

    mpvue开发微信小程序框架的使用注意事项: 1.路由跳转,引用mpvue-router-patch 在main.js文件中引入控件:import MpvueRouterPatch from 'mpv ...

  4. thymeleaf常用属性

    转 作者:ITPSC 出处:http://www.cnblogs.com/hjwublog/   th:action 定义后台控制器路径,类似<form>标签的action属性. 例如: ...

  5. python-crud

    Python Fast CRUD https://github.com/aleimu/python-crud 目的 本项目采用了一系列Python中比较流行的组件,可以以本项目为基础快速搭建Restf ...

  6. Python装饰器 (转)

    多个装饰器执行的顺序就是从最后一个装饰器开始,执行到第一个装饰器,再执行函数本身. #多个装饰器 import time def deco01(func): def wrapper(*args, ** ...

  7. 【WPF】 InkCanvas 书写毛笔效果

    首先贴出本文参考学习的文章吧. https://www.cnblogs.com/LCHL/p/9055642.html#4206298 感谢这位懒羊羊的代码和讲解(下简称羊博主),我在此基础上稍微加了 ...

  8. 【Android】drawable VS mipmap

    Android Studio 创建工程后默认的资源文件夹如下图所示: 一直有些疑惑的是 mipmap 和 drawable 文件夹有什么区别,以及是否还需要创建 drawable-xhdpi, dra ...

  9. 使用JavaScript的XMLHttpRequest+fromdata 传递blob到后端

    需要上传网页录音文件到服务器,写的艰辛,终于好了,C#端的代码失败的留作纪念,JS端也有失败的案例,就不放上来了 JavaScript: var form = new FormData(); form ...

  10. spring boot中的声明式事务管理及编程式事务管理

    这几天在做一个功能,具体的情况是这样的: 项目中原有的几个功能模块中有数据上报的功能,现在需要在这几个功能模块的上报之后生成一条消息记录,然后入库,在写个接口供前台来拉取消息记录. 看到这个需求,首先 ...