Promise学习笔记


一、回调函数的同步与异步

1、同步回调函数

    const arr = [1, 3, 5]
    arr.forEach(item => { // 遍历回调, 同步回调函数, 不会放入列队, 一上来就要执行完
      console.log(item)
    })
    console.log('forEach()之后')

2、异步回调函数

    setTimeout(() => { // 异步回调函数, 会放入队列中将来执行
      console.log('timout callback()')
    }, 0)
    console.log('setTimeout()之后')

二、常见错误

1、错误的类型

1、错误的类型

Error: 所有错误的父类型
ReferenceError: 引用的变量不存在
TypeError: 数据类型不正确的错误
RangeError: 数据值不在其所允许的范围内
SyntaxError: 语法错误

2、错误处理

捕获错误: try … catch 为了捕获到错误之后还可以继续进行后面的代码
抛出错误: throw error

3、错误对象

message属性: 错误相关信息
stack属性: 函数调用栈记录信息

三、Promise流程

在这里插入图片描述

四、为什么要用Promise

1、指定回调函数的方式更加灵活:

旧的: 必须在启动异步任务前指定
promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束指定)

  • 也就是说在异步任务开始之前回调函数就得写好,不能说已经结束了以后才去获取回调的值,那时候已经获取不到了,而promise则可以在任何时候都可以绑定回调函数

2、解决回调地狱的问题

  • 回调地狱:进行多个串联的异步函数时,当前的异步函数需要上一层异步函数的回调函数的结果作为条件,一层层嵌套
    • promise是通过.then方法从上到下,结构清晰,而且不需要写失败的回调,只要写一个.catch即可获得中间任意一个失败的回调(异常传透),但是他还存在回调函数,不是纯碎的同步编码方式
    • 最优解:async / await ,没有回调函数,同步编码方式

五、Promise的一些API

1、Promise构造函数: Promise (excutor) {}

excutor函数: 同步执行 (resolve, reject) => {}
resolve函数: 内部定义成功时我们调用的函数 value => {}
reject函数: 内部定义失败时我们调用的函数 reason => {}
说明: excutor会在Promise内部立即同步回调,异步操作在执行器中执行

2、Promise.prototype.then方法: (onResolved, onRejected) => {}

onResolved函数: 成功的回调函数 (value) => {}
onRejected函数: 失败的回调函数 (reason) => {}
说明: 指定用于得到成功value的成功回调和用于得到失败reason的失败回调
返回一个新的promise对象

3、Promise.prototype.catch方法: (onRejected) => {}

onRejected函数: 失败的回调函数 (reason) => {}
说明: then()的语法糖, 相当于: then(undefined, onRejected)

4、Promise.resolve方法: (value) => {}

value: 成功的数据或promise对象
说明: 返回一个成功/失败的promise对象

5、Promise.reject方法: (reason) => {}

reason: 失败的原因
说明: 返回一个失败的promise对象

6、Promise.all方法: (promises) => {}

promises: 包含n个promise的数组
说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败

7、Promise.race方法: (promises) => {}

promises: 包含n个promise的数组
说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态

六、Promise的回调函数

1、不管是成功的回调函数还是失败的回调函数,都是异步的,即使条件满足了也不是立即执行
2、 .then返回的是一个新的Promise对象
3、 .then后面还可以.then,但是后面的.then的回调函数的结果得依靠前面的.then的Promise对象return的值,如果没有return,那就是默认undefined (重点面试题)

new Promise((resolve, reject) => {
        resolve(1)
    }).then(
        value => { console.log('onResolved1', value) },
        reason => { console.log('onRejected1', reason) }
    ).then(
        value => { console.log('onResolved2', value) },
        reason => { console.log('onRejected2', reason) }
    )
console.log('***')
// ***   // 这个最先打印,说明.then里面的回调函数都是异步的
// onResolved1 1
// onResolved2 undefined
new Promise((resolve, reject) => {
        resolve(1)
    }).then(
        value => { 
            console.log('onResolved1', value) 
            return 2 // return Promise.resolve(3) // return Promise.reject(4) // throw 5
            },
        reason => { console.log('onRejected1', reason) }
    ).then(
        value => { console.log('onResolved2', value) },
        reason => { console.log('onRejected2', reason) }
    )
// onResolved1 1
// onResolved2 2   // onResolved2 3  // onRejected2 4  // onRejected2 5
new Promise((resolve, reject) => {
        reject(1)
    }).then(
        value => { console.log('onResolved1', value) },
        reason => { 
            console.log('onRejected1', reason) 
            // throw 5
            }
    ).then(
        value => { console.log('onResolved2', value) },
        reason => { console.log('onRejected2', reason) }
    )
// onRejected1 1
// onResolved2 undefined   // onRejected2 5
// 也就是说上一次的.then是不是成功的回调不影响下一次.then的回调结果,只要不是throw,那么下一个.then就是成功的回调onResolved(),没有return值的话成功的回调值就是undefined

4、如果想要在.then里面再写一个异步操作,必须得包在new promise里面,然后return出去

new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log("执行任务1(异步)")
        resolve(1)
      }, 1000);
    }).then(
      value => {
        console.log('任务1的结果: ', value)
        console.log('执行任务2(同步)')
        return 2
      }
    ).then(
      value => {
        console.log('任务2的结果:', value)
        
        return new Promise((resolve, reject) => {
          // 启动任务3(异步)
          setTimeout(() => {
            console.log('执行任务3(异步))')
            resolve(3)
          }, 1000);
        })
      }
    ).then(
      value => {
        console.log('任务3的结果: ', value)
      }
    )

5、异常传透(重点面试题)

new Promise((resolve, reject) => {
        reject(1)
    }).then(
        value => { console.log('onResolved1', value) },
        // reason => { throw reason }
        // reason => Promise.reject(reason)
    ).then(
        value => { console.log('onResolved2', value) },
        // reason => { throw reason }
    ).then(
        value => { console.log('onResolved3', value) },
        // reason => { throw reason }
    ).catch(
        reason => { console.log('onRejected', reason) }
    )
// 相当于每一个.then里面都加了一个 reason => { throw reason } 或者 reason => Promise.reject(reason)   可加可不加
// 如果中间哪一个成功回调了,底下的.catch就不走了

6、中断promise链(重点面试题)

  • 返回一个panding的promise,这样就没有resolved也没有rejected状态了,那么后面依赖这个状态的.then就一直不动了,这样就实现了中断promise链
  • .catch返回的也是一个Promise对象,也可以.then
new Promise((resolve, reject) => {
        reject(1)
    }).then(
        value => { console.log('onResolved1', value) },
        reason => { throw reason }
    ).then(
        value => { console.log('onResolved2', value) },
    ).then(
        value => { console.log('onResolved3', value) },
    ).catch(
        reason => { 
            console.log('onRejected', reason) 
            return new Promise(()=>{}) // 返回一个panding的promise
            }
    ).then(
        value => { console.log('onResolved4', value) },
        reason => { console.log('onRejected4', reason) }
    )

七、async await

1、async 函数

  • 函数的返回值为promise对象
  • promise对象的结果由async函数执行的返回值决定
async function fn1() {
        return 1 // 相当于 return Promise.resolve(1)
        // throw 1 // 相当于 return Promise.reject(1)
    }
    const result = fn1()
    result.then(
        value => {
            console.log('onResolved', value)
        },
        reason => {
            console.log('onRejected', reason)
        }
    )
    // onResolved 1

2、await 表达式

  • await右侧的表达式一般为promise对象, 但也可以是其它的值
  • 如果表达式是promise对象, await返回的是promise成功的值value
  • 如果表达式是其它值, 直接将此值作为await的返回值
function fn1() {
        return Promise.resolve(1)
    }
    // 用到await 必须加上async
    async function fn2() {
        const result = await fn1() // 使用await就可以不用.then而直接获取promise成功的value
        console.log(result);  // 1
    }
    fn2()

3、async await的注意点

  • await必须写在async函数中, 但async函数中可以没有await
  • await只能获得promise成功的结果value,如果await的promise失败了, 就会抛出异常, 需要通过try…catch来捕获处理,并且try…catch也得在async里面
    function fn1() {
            return Promise.reject(1)
        }
        // 用到await 必须加上async
        async function fn2() {
            const result = await fn1()
            console.log(result);
        }
        fn2()
        // 此时就会报错,因为await只能获得成功回调的结果
    // 如果promise的值是失败的回调,那么await会报错,只能用try...catch来获得promise失败的值
    function fn1() {
            return Promise.reject(2)
            // throw 2
        }
        // 用到await 必须加上async
        async function fn2() {
            try {
                const result = await fn1()
                console.log('onResolved()', result)
            } catch (error) {
                console.log('onRejected()', error) // onRejected() 2
            }
        }
        fn2()

八、JS异步之宏队列与微队列

在这里插入图片描述
1、js中用来存储待执行的回调函数的队列包含2个不同特定的队列
2、宏列队: 用来保存待执行的宏任务(回调), 比如: 定时器回调/DOM事件回调/ajax回调
3、微列队: 用来保存待执行的微任务(回调), 比如: promise的回调/MutationObserver的回调
4、JS执行时会区别这2个队列

  • JS引擎首先必须先执行所有的初始化同步任务代码
  • 每次准备取出第一个宏任务执行前, 都要将所有的微任务一个一个取出来执行
  • 同步任务 > 微队列 > 宏队列

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值