JavaScript异步编程

目录

  • JavaScript采用单线程模式工做的缘由
  • 单线程的优点和弊端
  • 同步模式与异步模式面试

    • 同步模式
    • 异步模式
    • 同步模式API和异步模式API的特色
  • 实现JavaScript异步编程的几种方式编程

    • 回调函数 —— 全部异步编程方案的根基
    • Promise —— 更优的异步编程解决方案
    • Generator
    • async/await —— 异步操做的终极解决方案

JavaScript采用单线程模式工做的缘由

最先JavaScript语言就是运行在浏览器端的语言,目的是为了实现页面上的动态交互。实现页面交互的核心就是DOM操做,这就决定了它必须使用单线程模型,不然就会出现很复杂的线程同步问题。segmentfault

假设在 js中有多个线程一块儿工做,其中一个线程修改了这个 DOM元素,同时另外一个线程又删除了这个元素,此时浏览器就没法明确该以哪一个工做线程为准。因此为了不线程同步的问题,从一开始, js就设计成了单线程的工做模式。

因此,js是单线程工做模式,若是有多个任务,任务须要排队,一个一个依次去执行。浏览器

单线程的优点和弊端

  • 优点:更安全,更简单
  • 弊端:效率低,有些能够同时执行的任务必须等待。若是中间有一个特别耗时的任务,其余的任务就要等待很长的时间,会出现假死的状况。

为了解决这种问题,js有两种任务的执行模式:安全

同步模式(Synchronous)异步模式(Asynchronous)异步

同步模式与异步模式

同步模式

指的是代码的任务依次执行,后一个任务必须等待前一个任务结束才能开始执行。程序的执行顺序和代码的编写顺序是彻底一致的。在单线程模式下,大多数任务都会以同步模式执行。async

console.log('global begin')
function bar () {
    console.log('bar task') 
}
function foo () {
    console.log('foo task')
    bar()
}
foo()
console.log('global end')

// global begin
// foo task
// bar task
//global end

// 使用调用栈的逻辑

为了不耗时函数让页面卡顿和假死,因此还有异步模式。异步编程

异步模式

该模式不会去等待这个任务的结束才开始下一个任务,都是开启事后就当即日后执行下一个任务,此时异步线程会单独执行异步任务,耗时函数的后续逻辑会经过回调函数的方式定义,执行事后会将回调放到消息队列中,js主线程执行完任务事后会依次执行消息队列中的任务。这里要强调,js是单线程的,浏览器不是单线程的,有一些API是有单独的线程去作的。函数

下面看一个简单的异步模式的例子:线程

console.log('global begin')
// 延时器
setTimeout(function timer1 () {
    console.log('timer1 invoke')
}, 1800)
// 延时器中又嵌套了一个延时器
setTimeout(function timer2 () {
    console.log('timer2 invoke')
    setTimeout(function inner () {
        console.log('inner invoke')
    }, 1000)
}, 1000)
console.log('global end')

// global begin
// global end
// timer2 invoke
// timer1 invoke
// inner invoke

//除了调用栈,还用到了消息队列和事件循环

异步模式对于JavaScript语言很是重要,没有它就没法同时处理大量的耗时任务。对于开发者而言。单线程下面的异步最大的难点就是代码执行的顺序混乱 ,因此面试题里面百分百会考这里的内容 - -|||

同步模式API和异步模式API的特色

同步模式的API的特色:任务执行完代码才会继续往下走,例如:console.log

异步模式的API的特色:下达这个任务开启的指令以后代码就会继续执行,代码不会等待任务的结束

实现JavaScript异步编程的几种方式

回调函数 —— 全部异步编程方案的根基

回调函数:由调用者定义,交给执行者执行的函数

// callback就是回调函数
// 就是把函数做为参数传递,缺点是不利于阅读,执行顺序混乱。
function foo(callback) {
    setTimeout(function(){
        callback()
    }, 3000)
}

foo(function() {
    console.log('这就是一个回调函数')
    console.log('调用者定义这个函数,执行者执行这个函数')
    console.log('其实就是调用者告诉执行者异步任务结束后应该作什么')
})

还有其余的一些实现异步的方式,例如:事件机制和发布订阅。这些也都是基于回调函数之上的变体。

Promise —— 更优的异步编程解决方案

主要为了解决回调地狱问题,详细了解参考 Promise(更优的异步编程解决方案)

Generator

详细了解参考 Generator -> Generator异步方案

async/await —— 异步操做的终极解决方案

详细了解参考 async&await -> async/await处理多回调异步