异步小记

作者: _Dot912 | 来源:发表于2017-11-03 16:23 被阅读0次

    首先了解一些概念:

    1. 进程 & 线程:
    • 进程:
      是系统资源分配和调度的单元,一个运行着的程序就对应了一个进程。一个进程包括了运行中的程序和程序所使用到的内存和系统资源。
      单核CPU在同一时间内只有一个进程在运行,但单核CPU也能实现多任务同时运行,比如你边听网易云音乐的每日推荐歌曲,边在网易有道云笔记上写博文。这算是多进程,运行的机制就是一会儿播放一下歌,一会儿响应一下你的打字,但由于CPU切换的速度很快,你根本感觉不到,以至于你认为这两个进程是在同时运行的。进程之间是资源隔离的。
    • 线程:
      是进程的执行者,一个进程至少会开启一个线程。比如网易云音乐一边播放音频,一边显示歌词。多进程的运行其实也就是通过进程中的线程来执行的。一个进程下的线程是共享资源的,多个线程同时操作同一资源时就出现资源争抢的问题。
    1. 并行 & 并发:
    • 并行:
      指程序的运行状态,在同一个时间内有几件事情并行在处理。由于一个线程在同一时间只能处理一件事情,所以并行需要多个线程在同一时间执行多件事情。
    • 并发:
      指程序的设计结构,在同一时间内多件事情能被交替地处理。重点是,在某个时间内只有一件事情在执行。比如单核CPU能实现多任务运行的过程就是并发的。
    1. 同步 & 异步
    • 同步:
      从上往下一步步执行代码,一定要等某一个任务执行完了,得到结果,才执行下一个任务。同步是调用者主动等待调用的过程。
    function taskSync = function(){
      return '同步任务的返回值'
    }
    
    var result = taskSync() // 那么 result 就是同步任务的结果
    otherTask()             // 然后执行下一个任务
    
    • 异步:
      程序发出调用后,不等当前任务执行完,直接执行下一个任务。当前任务返回的是一个timer id而不是异步执行的结果。凡是有回调函数/setTImeout/setInterval/addEventListener/Ajax请求的场景,都是异步事件。
    function taskAsync = function(){
      var result = setTimeout(function(){
        console.log('异步任务的结果')
      }, 3000)
      return result
    }
    
    var result = taskAsync() // result 不是异步任务的结果,而是一个 timer id
    otherTask()              // 立即执行其他任务,不等异步任务结束
    

    回调函数经常用于获取异步任务的结果

    function taskAsync = function(callback){
      var result = setTimeout(function(){
        callback('异步任务的结果')
      }, 3000)
      return result
    }
    
    taskAsync(function callback(result){
      console.log(result) // 三秒钟后,这个 callback 函数会被执行
    })
    otherTask()              // 立即执行其他任务,不等异步任务结束
    

    那么为什么需要异步呢?
    在执行某个非常耗时的任务时候,同步执行的逻辑会锁死后面所有的代码,而有了异步,那么浏览器将异步代码抽离出同步执行线程,放入异步中执行,首先避免的浏览器假死,第二个就是利用了异步线程加快了整体代码执行速度。

    1. 阻塞 & 非阻塞
    • 阻塞:
      指调用在等待的过程中线程被“挂起”(CPU资源被分配到其他地方去了)。
    • 非阻塞:
      指等待的过程中CPU资源还在该线程中,线程还能做其他的事情。

    浏览器拥有哪些线程

    一个浏览器通常由以下几个常驻的线程:

    • 渲染引擎线程:顾名思义,该线程负责页面的渲染
    • JS引擎线程:负责JS的解析和执行
    • 定时触发器线程:处理定时事件,比如setTimeout, setInterval
    • 事件触发线程:处理DOM事件
    • 异步http请求线程:处理http请求

    需要注意的是,渲染线程和JS引擎线程是不能同时进行的。渲染线程在执行任务的时候,JS引擎线程会被挂起。因为JS可以操作DOM,若在渲染中JS处理了DOM,浏览器可能就不知所措了。

    JavaScript的单线程

    JavaScript是一个单线程语言,浏览器只会分配一个js引擎线程来解析和执行js同步代码。单线程即任务是串行的,后一个任务需要等待前一个任务的执行。

    • 基于以下原因设计者将JavaScript设计为单线程
      • 假设两个JS线程同时操作DOM或者争夺唯一性资源,那么浏览器需要引入锁的概念来决定这两个JS的操作有效性,为了避免引入锁带来的复杂性,JS就被设计为单线程。
      • JS当初是以i/o为目标而设计的语言,所以单线程也是为了避免资源的浪费。

    参考资料

    相关文章

      网友评论

        本文标题:异步小记

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