一.Promise
1.什么是Promise?
- Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
- 从语法上说,promise 是一个对象,从它可以获取异步操作的的最终状态(成功或失败)。
- Promise是一个构造函数,对外提供统一的
API,自己身上有all、reject、resolve等方法,原型上有then、catch等方法。
2.Promise的两个特点
1.Promise对象的状态不受外界影响
(1)pending 初始状态
(2)fulfilled 成功状态
(3)rejected 失败状态
Promise 有以上三种状态,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态
2.Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由 pending变成fulfilled或者由pending变成rejected
3.Promise的API
then()方法
then 方法就是把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。
而 Promise 的优势就在于这个链式调用。我们可以在 then 方法中继续写 Promise 对象并返回,然后继续调用 then 来进行回调操作。
可有两个参数,第一个是成功 resolve 调用的方法,第二个是失败 reject 调用的方法
下面做一个买笔写作业上交的演示,它们是层层依赖的关系,下一步的的操作需要使用上一部操作的结果。(这里使用 setTimeout 模拟异步操作),正式开发可以用 ajax 异步
reject()方法:
我们通过 resolve 方法把 Promise 的状态置为完成态(Resolved),这时 then 方法就能捕捉到变化,并执行“成功”情况的回调。
而 reject 方法就是把 Promise 的状态置为已失败(Rejected),这时 then 方法执行“失败”情况的回调(then 方法的第二参数)
catch()方法:
用来指定 reject 的回调。当执行 resolve 的回调时,如果抛出异常了,那么也不会报错卡死 js,而是会进到这个 catch 方法中。
all()方法:
Promise 的 all 方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
race()方法:
race 按字面解释,就是赛跑的意思。race 的用法与 all 一样,只不过 all 是等所有异步操作都执行完毕后才执行 then 回调。而 race 的话只要有一个异步操作执行完毕,就立刻执行 then 回调。
注意:其它没有执行完毕的异步操作仍然会继续执行,而不是停止。
二.async、await
- async
async 是“异步”的简写, async 用于申明一个异步的 function - await
await 可以认为是 async wait 的简写,await 用于等待一个异步方法执行完成。
特点:
- asayc的用法,它作为一个关键字放到函数前面,这样普通函数就变为了异步函数
- 异步async函数调用,跟普通函数的使用方式一样
- 异步async函数返回一个promise对象
- async函数配合await关键字使用(阻塞代码往下执行)是异步方法,但是阻塞式的
async/await的优点
- 方便级联调用:即调用依次发生的场景;
- 同步代码编写方式: Promise使用then函数进行链式调用,一直点点点,是一种从左向右的横向写法;async/await从上到下,顺序执行,就像写同步代码一样,更符合代码编写习惯;
- 多个参数传递: Promise的then函数只能传递一个参数,虽然可以通过包装成对象来传递多个参数,但是会导致传递冗余信息,频繁的解析又重新组合参数,比较麻烦;async/await没有这个限制,可以当做普通的局部变量来处理,用let或者const定义的块级变量想怎么用就怎么用,想定义几个就定义几个,完全没有限制,也没有冗余工作;
- 同步代码和异步代码可以一起编写: 使用Promise的时候最好将同步代码和异步代码放在不同的then节点中,这样结构更加清晰;async/await整个书写习惯都是同步的,不需要纠结同步和异步的区别,当然,异步过程需要包装成一个Promise对象放在await关键字后面;
- sync/await是对Promise的优化: async/await是基于Promise的,是进一步的一种优化,不过在写代码时,Promise本身的API出现得很少,很接近同步代码的写法;