zoukankan      html  css  js  c++  java
  • setTimeout用法(Event Loop简介、for循环中应用、vue中应用)

    setTimeout基本用法

    setTimeout(code,millisec)

    setTimeout函数接受两个参数,第一个参数code是将要推迟执行的函数名或者一段代码,第二个参数millisec是推迟执行的毫秒数。

    例如:

    setTimeout('console.log(2)',100);//直接在setTimeout中直接执行代码, 需要以字符串的形式去写,引擎内部会将字符串转为可执行的代码
    setTimeout(function(){console.log(2)},100);

    什么是 Event Loop

    Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制。

    JavaScript语言就采用这种机制,来解决单线程运行带来的一些问题。

    在程序中设置两个线程:一个负责程序本身的运行,称为"主线程";另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")

     

    上图主线程的绿色部分,还是表示运行时间,而橙色部分表示空闲时间。每当遇到I/O的时候,主线程就让Event Loop线程去通知相应的I/O程序,然后接着往后运行,所以不存在红色的等待时间。等到I/O程序完成操作,Event Loop线程再把结果返回主线程。主线程就调用事先设定的回调函数,完成整个任务。

    可以看到,由于多出了橙色的空闲时间,所以主线程得以运行更多的任务,这就提高了效率。这种运行方式称为"异步模式"(asynchronous I/O)或"非堵塞模式"(non-blocking mode)。

    执行顺序

    console.log(1);
    //Time1
    setTimeout(function(){
        console.log(2);
    },300);for (var i = 0;i<10000;i++) {
        console.log(4);
    }
    //Time2
    setTimeout(function(){
        console.log(3);
    },300);

    运行结果:循环中的方法会先执行,然后再执行settimeout中的方法。

     for循环中的setTimeout(异步操作)

    function test() {
        for (var i = 0; i < 5; ++i) {
            setTimeout(function() {
                console.log("index is :", i);
            }, 1000);
        }
    }
    test();

    结果会显示:

    该操作几乎是在同一时间完成,setTimeout定时根本就没有起作用,这是因为:单线程的js在操作时,对于这种异步操作,会先进行一次“保存”,for循环执行结束后,i的值已经变成5,setTimetout调用均是在for循环结束后进行的,所以自然而然输出都是5。一般情况下,我们使用递归实现:

    function test(i) {
        if (i< 5) {
            console.log("index is :", i);
            setTimeout(function() {
                box7(i+ 1);
            }, 1000)
        }
    }
    test(0);

     我们也可以使用ES6中 async     Promise 实现,代码如下:

    var asyncFunc = function(arr, i) {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                arr.push(i);
                console.log("index is : ", i);
                resolve();//异步操作完成后执行resolve方法,配合.then使用,本例子中未使用到。
            }, 1000);
        });
    }
    var box5 = async function() {
        var arr = [];
        for (var i = 0; i < 5; i++) {
            await asyncFunc(arr, i);//async函数执行时,如果遇到await就会先暂停执行,等待Promise对象异步操作完成后,恢复async函数的执行并返回解析值。
        }
        console.log(arr);
    }
    box5(); 

     补充20200611:

    解决办法一

    for (var i = 0; i < 5; i++) { 
         (function(i){      //立刻执行函数
            setTimeout(function (){
                console.log(i);  
             },1000);  
         })(i);    
    }
    这里用到立刻执行函数。这样 console.log(i); 中的i就保存在每一次循环生成的立刻执行函数中的作用域里了。

    解决办法二

    for (let i = 0; i < 5; i++) {     //let 代替 var
        setTimeout(function (){
            console.log(i);  
         },1000);  
    }

    let 为代码块的作用域,所以每一次 for 循环,console.log(i); 都引用到 for 代码块作用域下的i,因为这样被引用,所以 for 循环结束后,这些作用域在 setTimeout 未执行前都不会被释放。

    setTimeout在vue中应用

    vue中直接使用this,此时的this指向的是window对象,虽然end方法仍然被执行了,但是没有延迟1s后执行的效果。

    setTimeout(this.end(),1000);

    正确的做法是方法中将this存在变量that中,此时执行setTimeout函数时,setTimeout函数内的that就会访问到这个变量,就会得到当前对象。

    export default {
     methods: {
      start: function () {
       let that=this
       setTimeout(function()  {
        that.end()
       }, 1000);
      }
     }

    也可以使用箭头函数:

    export default {
      methods: {
       start: function () {
        setTimeout(() => {
         this.end()
        }, 1000);
       }
      }
     

     参考:

    http://www.ruanyifeng.com/blog/2013/10/event_loop.html

  • 相关阅读:
    自己学习编程时间比较短,现在把一下自己以前刚刚接触C++时的程序上传一下,有空可以看看
    Scene is unreachable due to lack of entry points and does not have an identifier for runtime access via -instantiateViewControllerWithIdentifier解决办法
    CocosPods 每次install pod 都卡在analyzing
    NSArray,NSMutable和NSSet,NSMutableSet和NSDictionary,NSMutableDictionary用法
    准备离职,工作的一些细节记录
    SpriteBuilder 不能对设置spriteframe的sprite进行设置dynamic Physics解决办法
    SpriteBuilder 不能 Portrait
    LLVM和GCC的区别
    cocos2d 3.3 安装教程
    浅谈 关于ARC循环引用得问题
  • 原文地址:https://www.cnblogs.com/liangtao999/p/13089966.html
Copyright © 2011-2022 走看看