美文网首页
学习笔记(二)—— 异步编程

学习笔记(二)—— 异步编程

作者: 彪悍de文艺青年 | 来源:发表于2020-08-25 16:19 被阅读0次

    最近参加拉勾教育大前端高薪训练营,开始对前端知识体系进行一个系统的扩展跟学习,通过每天定期的学习,对一些不常使用的知识点进行了了解和补充,同时对已经使用过的知识点温故而知新
    在此记录学习笔记,并根据学习进度定时跟新

    单线程JavaScript

    • 为了避免多线程同步(操作DOM)问题
    • JS执行环境中,负责执行代码的线程只有一个
    • 优点:
      • 安全
      • 简单
    • 缺点:
      • 耗时任务阻塞执行

    同步模式

    同步代码依次加入调入栈,执行完成后从调用栈移除

    异步模式

    • 不会等待任务结束再执行,开启后立即执行下一个任务

    • 后续逻辑通过回调函数定义

    • 使单线程JavaScript能够执行大量耗时任务

    • 缺点:代码执行顺序混乱

    • JavaScript是单线程,但浏览器并不是单线程

    异步任务交给异步线程执行,执行完成后,将回调逻辑加入消息队列,当调用栈中的任务执行完成后,事件循环将消息队列中的第一个任务加入调用栈执行,开始下一轮事件循环

    Promise

    由CommonJS社区提出了Promise的规范,在ES2015中被标准化

    • Promise有三种状态

      • pending
      • fulfilled
        • 调用resolve
      • rejected
        • 调用reject
    • Promise的状态一旦确定后就不能再被修改

    • 使用案例

      • 模拟实现Promise版ajax

        function ajax(url) {
            return new Promise(function(resolve, reject) {
                const xhr = new XMLHttpRequest()
                xhr.open('GET', url)
                xhr.responseType = 'json'
                xhr.onload = function() {
                    if (this.status === 200) {
                        resolve(this.response)
                    } else {
                        reject(new Error(this.statusText))
                    }
                }
                xhr.send()
            })
        }
        
    • 常见错误

      • 嵌套调用
    • 链式调用

      • then方法会返回一个全新的Promise对象
      • then方法为之前返回的Promise对象注册回调
      • 前面then方法中回到函数的的返回值会作为后面then方法回到的参数传入
      • 如果回调中返回的是Promise,那后面的then的回调会等待Promise结束
      • 如果传入then的参数非回调函数,这个then会被忽略执行(跳过)
    • 异常处理

      • 两种方式
        • then方法的第二个参数回调函数中捕获
        • catch方法回调函数中捕获
      • 差异
        • then方法的第二个参数回调函数可以捕获then之前的Promise产生的异常
        • cache方法可以捕获前面Promise以及then中产生的异常,实际为前面then返回的新Promise,只不过异常通过then的链式调用传递了
      • 全局异常捕获
        • web环境window.addEventListener注册unhandledrejection事件
        • node环境process.on注册unHandledRejection事件
        • 不推荐采用全局捕获的方式处理异常,而应该在代码中明确捕获异常并处理
    • 静态方法

      • Promise.resolve()
        • 如果传入的是普通的值,返回一个已经resolve的Promise对象,Promise.reslve(value)等同于new Promise(resolve => resolve(value))
        • 如果传入的是Promise对象,则直接返回传入的Promise对象本身,使用===比较相等
        • 如果传入的是thenable对象(实现了then方法并带有resolve,reject回调函数参数的对象),则转化为相应then方法的Promsie对象,这个特性可以用来转化第三方库实现的Promise对象为标准Promise对象
      • Promise.reject()
        • 无论传入什么值,都会作为reject的原因传入异常捕获回调
    • 并行执行

      • Promise.all()
        • 接收一个Promise对象数组作为参数,返回一个Promise对象
          • 数组中的所有Promise都被resolve后,将所有Promsie对象resolve返回的数组传入then的回调
          • 如果有Promise被reject,则返回第一个被reject的Promise的状态传入then或cache的回调
      • Promise.race()
        • 接收一个Promise对象数组作为参数,数组中的任意Promise状态发生变化,返回一个Promise对象,将第一个发生状态变化的Promise状态传入相应的回调
    • 执行时序

      • Promise的回调作为微任务,其他还有node的process.nextTick,MutationObserver
      • setTimeout、setInterval等作为宏任务

    Generator异步方案

    ES2015引入,生成器函数,使异步调用操作扁平化

    • 函数名前加*为生成器函数,调用生成起函数返回一个生成器对象

    • 函数中通过yield关键字,可以暂停函数执行

    • 生成器对象通过调用next()方法,执行到下一个yield之前的代码,并返回一个对象,包含value和done两个属性

      • value:yield之后的表达式的值
      • done:表示生成器是是否执行完成
    • 调用next()方法传入参数,则参数值会作为yield的返回值,传递给yield左边的变量

    • 调用throw()方法,会抛出异常,可以由生成器函数内部捕获,也可以由函数外部捕获

    • 生成器自动执行函数(执行器)co模拟实现

      function co(generator) {
          function handleResult(result) {
              if(result.value.done) return
       
              result.value.then(data => {
                  handleResult(generator.next(data))
              }, error => generator.throw(error))
          }
          handleResult(generator.next())
      }
      

    async/await

    ES2017引入,Generator的语法糖,异步操作自动执行,更加语义化

    • async函数返回一个Promise对象
      • 将await之前的代码放入Promise.resolve()
      • 将await之后的代码放入then
      • 如果执行异常,则放入Promise.reject()
    • await之后是一个Promise对象
      • 则Promise.resolve()回调的参数值作为await表达式的值
      • 抛出Promise.reject()的异常
    • await之后是一个常量,则将值作为参数,返回一个Promise.resolve()

    相关文章

      网友评论

          本文标题:学习笔记(二)—— 异步编程

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