promise

函数对象、实例对象

1.函数对象: 将函数作为对象使用时, 简称为函数对象。
2.实例对象: new 构造函数或类产生的对象, 我们称之为实例对象。

函数有个属性name指的是函数的名字:

function Person(){}

Person.name //Person

  

回调

我们定义的,我们没有调用,最终执行了。

1.同步的回调函数:

理解: 立即在主线程上执行, 不会放入回调队列中。
例子: 数组遍历相关的回调函数

2.异步的回调函数:

理解: 不会立即执行, 会放入回调队列中以后执行
例子: 定时器回调 / ajax回调

 

错误

1. 错误的类型

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

2. 错误处理

捕获错误: try{}catch(){}
抛出错误: throw error
 

3. 错误对象

message属性: 错误相关信息
stack属性: 记录信息
 
 

Promise是什么?

1.抽象表达:

(1).Promise是一门新的技术(ES6提出的)
(2).Promise是JS中异步编程的新方案(旧方案是谁?---纯回调)
 

2.具体表达:

(1).从语法上来说: Promise是一个内置构造函数
(2).从功能上来说: Promise的实例对象可以用来封装一个异步操作,并可以获取其成功/失败的值
 

用法

1.Promise不是回调,是一个内置的构造函数,是程序员自己使用new调用的。

2.new Promise的时候,要传入一个同步的回调函数,会立即在主线程上执行,它被称为executor函数(executor函数)

3.每一个Promise实例都有3种状态:初始化(pending)、成功(fulfilled)、失败(rejected)

4.每一个Promise实例在刚被new出来的那一刻,状态都是初始化(pending)

5.executor函数会接收到2个参数,它们都是函数,分别用形参:resolve、reject接收

1.调用resolve函数会:

(1).让Promise实例状态变为成功(fulfilled)

(2).可以指定成功的value。

2.调用reject函数会:

(1).让Promise实例状态变为失败(rejected)

(2).可以指定失败的reason。

 

1. 重要语法

new Promise(executor)构造函数
Promise.prototype.then方法

2. 基本编码流程

1.创建Promise的实例对象(pending状态), 传入executor函数

2.在executor中启动异步任务(定时器、ajax请求)

3.根据异步任务的结果,做不同处理:

3.1 如果异步任务成功了:

我们调用resolve(value), 让Promise实例对象状态变为成功(fulfilled),同时指定成功的value

3.2 如果异步任务失败了:

我们调用reject(reason), 让Promise实例对象状态变为失败(rejected),同时指定失败的reason

4.通过then方法为Promise的实例指定成功、失败的回调函数,来获取成功的value、失败的reason

注意:then方法所指定的:成功的回调、失败的回调,都是异步的回调。

 

3. 关于状态的注意点:

1.三个状态:

pending: 未确定的------初始状态

fulfilled: 成功的------调用resolve()后的状态

rejected: 失败的-------调用reject()后的状态

2.两种状态改变

pending ==> fulfilled

pending ==> rejected

3.状态只能改变一次!!

4.一个promise指定多个成功/失败回调函数, 都会调用吗?是的,都会被推入队列随后调用

 

API

1. Promise构造函数: new Promise (executor) {}
 
executor函数: 是同步执行的,(resolve, reject) => {}
resolve函数: 调用resolve将Promise实例内部状态改为成功(fulfilled)。
reject函数: 调用reject将Promise实例内部状态改为失败(rejected)。
说明: excutor函数会在Promise内部立即同步调用,异步代码放在excutor函数中。

2. Promise.prototype.then方法: Promise实例.then(onFulfilled,onRejected)
 
onFulfilled: 成功的回调函数 (value) => {}
onRejected: 失败的回调函数 (reason) => {}
特别注意(难点):then方法会返回一个新的Promise实例对象

3. Promise.prototype.catch方法: Promise实例.catch(onRejected)
 
onRejected: 失败的回调函数 (reason) => {}
说明: catch方法是then方法的语法糖, 相当于: then(undefined, onRejected)

4. Promise.resolve方法: Promise.resolve(value)
 
说明: 用于快速返回一个状态为fulfilled的或者rejected的Promise实例对象
备注:value的值可能是:(1)非Promise值  (2)Promise值

5. Promise.reject方法: Promise.reject方法(reason)
 
说明: 用于快速返回一个状态必为rejected的Promise实例对象
   
6. Promise.all方法: Promise.all(promiseArr)
 
promiseArr: 包含n个Promise实例的数组
说明: 返回一个新的Promise实例, 只有所有的promise都成功才成功, 成功的value是包含所有value的数组,只要有一个失败了就直接失败,失败的原因是第一个失败的reason。
 
7. Promise.allSettled()方法:
 
返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
       
8. Promise.race方法: Promise.race(promiseArr)
 
promiseArr: 包含n个Promise实例的数组
说明: 返回一个新的Promise实例, 成功还是很失败?以最先出结果的promise为准。
 
9. Promise.prototype.finally()

finally() 方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方式。
这避免了同样的语句需要在then()和catch()中各写一次的情况。

 
1. 如何改变一个Promise实例的状态?
         (1)执行resolve(value): 如果当前是pending就会变为fulfilled
         (2)执行reject(reason): 如果当前是pending就会变为rejected
         (3)执行器函数(executor)抛出异常: 如果当前是pending就会变为rejected
 

2. 改变Promise实例的状态和指定回调函数谁先谁后?

1.都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调

2.如何先改状态再指定回调?

延迟一会再调用then()

3.Promise实例什么时候才能得到数据?

如果先指定的回调(回调会被暂存到自身), 那当状态发生改变时, 回调函数就会拿出来调用, 得到数据
如果先改变的状态(状态也会被暂存到自身), 那当指定回调时, 回调函数就会立即调用, 得到数据

 

Promise实例.then()返回的是一个【新的Promise实例】,它的值和状态由什么决定?

1.简单表达: 由then()所指定的回调函数执行的结果决定

2.详细表达:

(1)如果then所指定的回调返回的是非Promise值a:
那么【新Promise实例】状态为:成功(fulfilled), 成功的value为a

(2)如果then所指定的回调返回的是一个Promise实例p:
那么【新Promise实例】的状态、值,都与p一致

(3)如果then所指定的回调抛出异常:
那么【新Promise实例】状态为rejected, reason为抛出的那个异常

 

中断promise链:

(1)当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数。

(2)办法: 在失败的回调函数中返回一个pendding状态的Promise实例。

 

promise错误穿透:

(1)当使用promise的then链式调用时, 可以在最后用catch指定一个失败的回调,

(2)前面任何操作出了错误, 都会传到最后失败的回调中处理了

备注:如果不存在then的链式调用,就不需要考虑then的错误穿透。

 

Promise的优势

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

  2. 支持链式调用, 可以解决回调地狱问题
    (1)什么是回调地狱:
      回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调函数执行的条件
    (2)回调地狱的弊病:
      代码不便于阅读、不便于异常的处理
    (3)一个不是很优秀的解决方案:
      then的链式调用
    (4)终极解决方案:
      async/await(底层实际上依然使用then的链式调用)
 

async与await

1. async修饰的函数
函数的返回值为promise对象
Promise实例的结果由async函数执行的返回值决定

2. await表达式
await右侧的表达式一般为Promise实例对象, 但也可以是其它的值
(1).如果表达式是Promise实例对象, await后的返回值是promise成功的值
(2).如果表达式是其它值, 直接将此值作为await的返回值

3. 注意:
await必须写在async函数中, 但async函数中可以没有await
如果await的Promise实例对象失败了, 就会抛出异常, 需要通过try...catch来捕获处理

 

await的原理

若我们使用async配合await这种写法:
1.表面上不出现任何的回调函数
2.但实际上底层把我们写的代码进行了加工,把回调函数“还原”回来了。
3.最终运行的代码是依然有回调的,只是程序员没有看见。

 

宏队列与微队列

宏队列:[宏任务1,宏任务2.....]
微队列:[微任务1,微任务2.....]
规则:每次要执行宏队列里的一个任务之前,先看微队列里是否有待执行的微任务
1.如果有,先执行微任务
2.如果没有,按照宏队列里任务的顺序,依次执行

posted on 2022-05-14 16:04  前端码牛  阅读(49)  评论(0编辑  收藏  举报

导航