zoukankan      html  css  js  c++  java
  • Promiseの相关小结

    前言

    网上关于Promise的文章确实是非常多了,但是自己实践的并不多,这里是针对自己的一个知识点小结和梳理,而且由Promise延伸出的关于事件循环的机制也是可以挖出很多东西的,不过这个总结可能就是涉及到一些皮毛,当然啦如果有错误欢迎提出_

    初定义

    定义:Promise对象用于一个异步操作的最终完成/失败及其结果值的表示。
    使用原因:避免回调嵌套层次过多。
    拥有状态:

    • pending:初始/未定状态,初始化Promise时,调用executor函数后的状态。
    • fulfilled:成功状态。
    • rejected:失败状态。

    状态转化:

    • pending -> fulfilled:操作成功
    • pending -> rejected:操作失败
      状态转化是单向的,不可逆转。

    最基本用法:
    可以看到创建一个Promise实例,传入的参数是一个函数,这个函数称为executor/执行器。

    new Promise((resolve, reject) => {
        if (success) {
            resolve(a) // pending to resolved
        } else {
            reject(err) // pending to rejectd
        }
    })
    

    方法

    Promise对象本身,有一些方法:

    • race()
    • reject()
    • resolve()
    • all()

    查看Promise的原型,发现它内置有几个方法:

    • catch()
    • finally()
    • then()

    Promise.prototype.then()

    • 参数:处理成功的函数,处理错误的函数
    • 返回值:返回一个Promise对象,所以可以链式调用。
    promise.then(
        () => { console.log('我是成功后被执行的') },
        () => { console.log('我是失败后被执行的') })
    

    Promise.prototype.catch()

    • 参数:捕捉的错误/reject()传来的参数
    • 返回值:返回一个Promise对象,所以可以链式调用。
    • Promise和then()中抛出错误能够不断传递,就能够在下一个catch()中统一处理,所以一般省略then中的第二个失败执行的函数。
    promise.then(
        () => { console.log('我是成功后被执行的') }
    ).catch(
        (err) => { console.log(err) })
    

    使用rejects()方法改变状态和抛出错误 throw new Error() 的作用是相同的

    Promise.all()

    • 参数:可迭代参数,如:数组。
    • 用途:处理一些并发的异步操作,需要保证每个都执行完毕。
    • 结果:状态全为fulfilled->fulfilled,否则->rejected。

    Promise.race()

    • 参数:可迭代参数,如:数组。
    • 用途:处理一些并发的异步操作,只需要其中一个执行完毕。
    • 结果:所有异步操作中有一个状态先改变,就采纳那个最先改变的状态为结果。

    Promise.resolve()

    • 参数:普通值、Promise对象、带有then的对象。
    • 结果:一般情况返回一个状态为fulfilled的Promise对象。解析发生错误则返回rejected的Promise对象。
    Promise.resolve('success')
    // 其中[[PromiseStatus]]:"resolved"
    
    Promise.reject('fail') 
    // 其中[[PromiseStatus]]:"rejected"
    
    Promise.resolve(Promise.reject('fail'))
    // 其中[[PromiseStatus]]:"rejected"
    

    由这个例子可以看出浏览器认为resolvedfulfilled是等价的,但Promise.resolve() 不一定让promise最终是fulfilled。所以对于resolved本身和fulfilled的区别,可以理解为resolved等价于compiled,即可能是成功也可能是失败。

    Promise.reject()

    • 参数: 发生异常的原因。
    • 结果:返回一个rejected状态的Promise对象。

    注意点

    状态变化

    • Promise状态只会改变一次。
    • 构造函数中的resolve()/reject()只有第一次执行有效,多次调用没有作用。
    • Promise状态改变,并且传递了一个值,后续调用.then()/.catch()都可直接拿到该值。

    参数/返回值

    • .then()/.catch()的参数应该是函数,传入非函数则会发生值穿透。
    Promise.resolve(1)
      .then(2)
      .then(Promise.resolve(3))
      .then(console.log)  //1
    
    • .then()/.catch()不能返回Promise本身,会造成死循环。
    • .then()/.catch()中return一个error对象并不会抛出错误,所以无法捕捉。

    因为返回任意一个非Promise 的值都会被包裹成Promise对象,即 return new Error('error!!!')等价于return Promise.resolve(new Error('error!!!'))

    执行顺序

    • Promise构造函数是同步执行的,resolve()/reject()后的代码也会执行。Promise.then()中的函数是异步执行的。**
      以下输出:1243
    const promise = new Promise((resolve, reject) => {
      console.log(1)
      resolve()
      console.log(2)
    })
    promise.then(() => {
      console.log(3)
    })
    console.log(4)
    
    • process.nextTickpromise.then属于microtasksetImmediate属于 macrotask。在每一次事件循环中,macrotask只会提取一个执行,而microtask会一直提取,直到microsoft队列为空为止。

    以下输出:end nextTick then setTimeout1 setTimeout2

    process.nextTick(() => {
      console.log('nextTick')
    })
    
    setTimeout(() => {
      console.log('setTimeout1')
    })
    
    Promise.resolve()
      .then(() => {
        console.log('then')
      })
      
    setTimeout(() => {
      console.log('setTimeout2')
    })
    
    console.log('end')
    

    补充:
    macrotasks:

    • setTimeout
    • setInterval
    • setImmediate
    • requestAnimationFrame
    • I/O
    • UI rendering

    microtasks:

    • process.nextTick
    • Promises
    • Object.observe
    • MutationObserver

    参考文章

    ES6关于Promise的用法
    Promise 必知必会(十道题)
    javascript中的异步 macrotask 和 microtask 简介
    Tasks, microtasks, queues and schedules
    Difference between microtask and macrotask within an event loop context

  • 相关阅读:
    关于我对区块链和比特币的看法
    叙Windows平台下基于MBR和UEFI的bootkit(一)--以MBR为例
    动若脱兔:深入浅出angr--初步理解符号执行以及angr架构
    面经
    倚天屠龙(一):妙用IDA Pro--利用IDAPython编写调试插件
    初生牛犊:Windows下Anti-sandboxes技术探究
    浮生半日:探究Python字节码
    抽丝剥茧:理解Android权限机制
    自古套路得人心:安全岗面经(人生苦短,请勿入坑二进制)
    点击按钮,复制微信号代码
  • 原文地址:https://www.cnblogs.com/rimochiko/p/12641040.html
Copyright © 2011-2022 走看看