异步小记

首先了解一些概念:

  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为目标而设计的语言,所以单线程也是为了避免资源的浪费。

参考资料

  • JavaScript 的 同步,异步,Event-Loop,线程
  • JavaScript单线程异步的背后——事件循环机制
  • 什么是异步
  • JS 事件循环机制 - 任务队列、web API、JS主线程的相互协同
  • Javascript线程的理解
  • javascript任务调度队列机制
  • 深入理解 JavaScript 运行机制
  • JavaScript中的函数节流
  • 探讨javascript函数节流

你可能感兴趣的:(异步小记)