首页 >社区问答列表 >javascript - JS 代码非顺序执行语句 单步运行正常,直接跑出问题

javascript - JS 代码非顺序执行语句 单步运行正常,直接跑出问题

  1. 想实现 弹框3s后自动隐藏,我设定了如下代码:

document.getElementById("alertMessageSel").style.display = "block";
document.getElementById("alertMessage").innerHTML = "两次输入手机号不一致!";
var t = Date.now();           
var t1 = Date.now() + 100;
while(t1 - t <= 3000) {
    t1 = Date.now();
};
document.getElementById("alertMessage").innerHTML = "";
document.getElementById("alertMessageSel").style.display = "none";

单步调试没有问题,会顺序执行,我指的是打断点,效果和我想象一样,但是不打断点直接运行就不会出现这个效果。
我想到了js在运行过程中运行应该有自己的执行方式。

2.想知道其中的运行机制,想了解如何实现,达到我预期的效果。

  • 巴扎黑
  • 巴扎黑    2017-06-26 10:52:144楼

    document.getElementById("alertMessageSel").style.display = "block";
    document.getElementById("alertMessage").innerHTML = "两次输入手机号不一致!";
    setTimeout(function () {
        document.getElementById("alertMessage").innerHTML = "";
        document.getElementById("alertMessageSel").style.display = "none";
    }, 3000);

    +0添加回复

  • 回复
  • 怪我咯
  • 怪我咯    2017-06-26 10:52:143楼

    楼主的这个,点击显示弹框的时候,添加一个settimeout间隔三秒后,自动隐藏弹框或者remove弹框对应的结构

    +0添加回复

  • 回复
  • 小葫芦
  • 小葫芦    2017-06-26 10:52:142楼

    什么是阻塞机制
    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);
    }, 10);

    }
    而实际上,这段代码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);
        }, 10);
    })(i)

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

    +0添加回复

  • 回复