美文网首页js基础
setTimeout与setInterval

setTimeout与setInterval

作者: blueblue_c41a | 来源:发表于2018-02-05 09:40 被阅读8次

    (用于什么情况?)

    (用setTimeout模拟setInterval)


    一、setTimeout需要注意的地方
    1、setTimeout共有4个参数

    最后那两个参数,将在1000毫秒之后回调函数执行时,作为回调函数的参数。

    setTimeout(function(a,b){
      console.log(a+b);
    },1000,1,1);
    
    2、被setTimeout推迟执行的回调函数是在全局环境执行,有可能不同于函数定义时的上下文环境
    var x = 1;
    var o = {
        x: 2,
        y: function(){
        console.log(this.x);
      }
    };
    // 回调函数的运行环境已经变成了全局环境
    setTimeout(o.y,1000);   // 1
    
    3、this问题
    function User(login) {
      this.login = login;
      this.sayHi = function() {
        console.log(this.login);
      }
    }
    var user = new User('John');
    
    // this指向全局
    setTimeout(user.sayHi, 1000); // undefined
    
    // 将user.sayHi放在函数中执行
    setTimeout(function() {
      // this指向user
      user.sayHi();
    }, 1000) // John
    

    二、setInterval的不足之处

    1、不去关心回调函数是否还在运行
    在某些情况下,函数可能需要比间隔时间更长的时间去完成执行。比如说是用setInterval每隔5秒对远端服务器进行轮询,网络延迟,服务器无响应以及其他因素将会阻止请求按时按成。结果会导致返回一串无必要的排成队列请求。

    2、忽视错误
    因为某些原因,setInterval调用的代码中会出现一个错误,但是代码并不会中止执行而是继续执行错误的代码。

    3、缺乏灵活性
    除了前面提到的缺点之外,我非常希望setInterval方法能有一个表明执行次数的参数而不是无休止的执行下去。


    三、用setTimeout模拟setInterval
    setTimeout(function(){
    
        //do something
    
        setTimeout(arguments.callee,interval);
    },interval)
    
    // 刷新股票
    refreshTick = () => {
        // 定时器 —— this.refreshTickInterval
        this.refreshTickInterval = setTimeout(this.refreshTick, 250)
        if (Object.keys(this.mixedTick).length !== 0) {
            this.props.doSocketTicks(this.mixedTick)
            // 刷新完,清空mixedTick
            this.mixedTick = {}
        }
    }
    // 注意unmount的时候要去除定时器
    // componentWillUnmount() {
        // 去除定时器
        // clearTimeout(this.refreshTickInterval)
    // }
    
    四、例题
    1、以下代码有什么区别,各自输出什么?
    for (var i = 0; i < 10; ++i) {
        setTimeout( function () {console.log(i)}, 0); 
    }
    for (var i = 0; i < 10; ++i) {
        setTimeout((function () {console.log(i)})(), 0);
    }
    
    解: image.png
    2、以下代码执行后,输出什么?
    setTimeout(function () {
      console.log(1);
    }, 0);
    
    Promise.resolve(function () {
      console.log(2);
    })
    
    new Promise(function (resolve) {
      console.log(3);
    });
    
    console.log(4);
    

    解:输出3 4 undefined 1

    js中的事件执行主要分为两个任务类型 macro task以及micro task 也就是宏仁务微任务

    宏仁务:script(全局任务),setTimeout ,setInterval ,setImmediate ,I/O ,UI rendering
    微任务:process.nextTick, promise, Object.observer, MutationObserver

    • 执行顺序为 script先进入函数调用栈,

    • 然后执行遇到任何其他宏仁务,比如遇到了setTimeout,就把setTimeout放进宏仁务队列中,遇到了微任务就放入微任务队列中,

    • 等到函数调用栈的所有内容出栈后 然后执行微任务队列,

    • 然后再回头执行宏仁务队列再进入函数调用栈再执行微任务队列,直到宏仁务队列执行完毕

    //异步队列:遇到setTimeout,放入宏仁务队列
    setTimeout(function () {
      console.log(1);
    }, 0);
    //写法错误:遇到promise,放入微任务队列,在主task之后立刻执行
    Promise.resolve(function () {
      console.log(2);
    })
    //立即执行:这里虽然遇到了promise,但是是用new声明的,也就是立即执行,所以会先输出3
    new Promise(function (resolve) {
      console.log(3);
    });
    //立即执行:第二输出4
    console.log(4);
    
    // 需要注意的是那个undefined并不是微任务输出的,
    // 而是console.log(4)输出的,具体可以控制台测试
    
    // 然后执行微任务,这个微任务并没有调用,所以也不会执行,
    // 然后执行宏仁务队列中的setTimeout,输出1
    

    相关文章

      网友评论

        本文标题:setTimeout与setInterval

        本文链接:https://www.haomeiwen.com/subject/wpgaaxtx.html