zoukankan      html  css  js  c++  java
  • 事件驱动模型

    从setTimeout说起
    这是一个JS引擎当中内置的定时器函数
    官方的定义如下

    setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式

    但是实践证明 , 即使是setTimeout(fn, 0)
    fn函数也不会立即被执行
    例如下列代码

    console.log(1);
    var timeFunc = function(){
        console.log(2);
    }
    setTimeout(timeFunc,0);
    console.log(3);
    执行的结果是1 3 2 , 而不是1 2 3

    JS引擎的单线程特性

    JS语言设计的一个很重要的特点就是 : JS是没有多线程的
    但是JS引擎是单线程 , 浏览器却可以是多线程 , JS引擎只是浏览器的一个线程而已
    定时器 网络请求 浏览器渲染等操作 , 都是由不同的线程去完成的
    比如下面这个例子

    var isEnd = true;
    window.setTimeout(function () {
        isEnd = false;
        }, 1000);
    while (isEnd);
    console.log('end');

    在1s之后 , 将isEnd置为false , 表面看来后面的死循环只会持续1s而已
    但是实际上这段代码会一直陷入死循环
    这也证明了setTimeout并不能实现多线程


    JS是基于事件驱动的语言 , 它的执行顺序遵循事件队列的机制 

    浏览器有各种各样的线程 , 这些线程的联系都是基于事件的 , 当JS引擎处理到与其他线程相关的代码 , 就会分发到其他的线程
    在这个过程中 , JS引擎并不会阻塞自己的线程等待其他线程执行完毕 , 而且其他线程执行完毕后添加事件任务告诉js引擎执行相关操作 , 这就是js的异步编程模型.

    拿上面的定时器函数来说 , 执行这个函数的时候 , 就会开启一个定时器线程( 注意: 这个线程并不属于JS引擎 ) , 这个线程会在指定时间后向事件队列中添加一个任务 , 这个任务就是执行传递给setTimeout的函数
    既然是队列 , 后入队的任务当然会在主线程的任务之后执行

    如果主线程的任务一直不结束 , 那么这个队列就会一直阻塞
    这同样也可以解释同步ajax请求 , 当后台响应较慢的时候造成的页面假死现象
    页面要与用户进行交互 , 依靠的是响应事件 , 比如鼠标点击事件等
    但是主线程任务一直不结束 , 点击事件的任务只能在后面排队 , 事件方法不会被执行 , 当然就有了假死现象
    当主线程任务结束的时候 , 这些事件方法仍然会执行

    由此可见官方对于settimeout的定义是有迷惑性的.应该给一个新的定义:

    在指定时间内, 将任务放入事件队列,等待js引擎空闲后被执行.

  • 相关阅读:
    js单体模式
    react实现递归搜索下拉查询目录树功能
    浏览器跨域问题分析
    css中清除浮动
    ts中的函数
    ts中类型
    RX.js6变化
    js对象模型3
    React数组变化之后,视图没有更新
    Mac安装yarn并配置环境变量PATH,运行报错问题解决
  • 原文地址:https://www.cnblogs.com/programInit/p/6363183.html
Copyright © 2011-2022 走看看