Promise 、async、await 的学习
js的同步和异步
首先我们需要复习一下 js 的同步和异步
JavaScript是一门单线程的语言,因此,JavaScript在同一个时间只能做一件事,单线程意味着,如果在同个时间有多个任务的话,这些任务就需要进行排队,前一个任务执行完,才会执行下一个任务,为了防止 ajax 这类任务执行等待时间过长,javascrpit 就设计了同步和异步任务
同步任务
同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务,当我们打开网站时,网站的渲染过程,比如元素的渲染,其实就是一个同步任务
异步任务
异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程,当我们打开网站时,像图片的加载,音乐的加载,其实就是一个异步任务
Es6的Promise异步规范
在 Es6 的 Promise 出来之前,我们一般都是使用回调函数来处理异步任务 ,在Promise规范提出后,异步编程就变的相对简单一些
Promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)
Promise并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据
Promise包括以下几个规范
- 一个promise可能有三种状态:等待
pending、已完成fulfilled、已拒绝rejected- 一个promise的状态只可能从
等待转到完成态或者拒绝态,不能逆向转换,同时完成态和拒绝态不能相互转换- promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致(即链式的then方法调用)
- then方法接受两个参数,(一般我们叫第一个回调参数为
res、第二个为err) ,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由等待态转换到拒绝态时调用,同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象
我们可以通过 if(typeof(Promise)==="function") 来测试浏览器是否支持promise
通过 new Promise 来进行 Promise 对象的创建
1 | new Promise( |
Promise.then()的链式调用示例,then 被按照顺序组织起来,一个一个的执行,每个执行完后就会变成 完成 状态并进行下一个
前面也提到了,then方法其实是接受两个参数,虽然大部分时候我们都比较关注成功时的回调,但第二个参数失败的回调可以帮我们处理一些异常,除此之外,我们还可以使用catch来捕获错误,reject 的东西一定进入 then 的第二个回调,当没有写第二个回调的时候,会进入catch,如果没有then, 也可以直接进入catch。
err处理异常和catch都会返回一个promise实例,并且是resolved状态所以不会影响后续的then的执行,否则将会把后续的then的状态变为rejected 并且不会执行他们所登记的异步函数
| then的链式调用 | 出错的then的链式调用 | ||||
|---|---|---|---|---|---|
|
|
async 和 await
async是作为函数的修饰符放在函数的前面 , 它的调用会返回一个promise对象,并且Promise还有PromiseStatus和promiseValue,如果async函数本身返回值,当调用该函数成功时内部会调用Promise.solve()方法把它转化成一个promise对象作为返回,如果 函数内部抛出错误,就会调用Promise.reject()返回一个promise对象,想要获取到async函数的执行结果,就要调用promise的then或catch来给它注册回调函数总结一下,
async函数的执行会返回一个promise对象,并且把内部的值进行promise的封装。如果promise对象通过then或catch方法又注册了回调函数,async函数执行完以后,注册的回调函数就会放到异步队列中,等待执行
await关键字只能放到async函数里面,await是等待的意思,等待直到Promise对象resolve,得到resolve的值作为await表达式的运算结果,我们一般在需要拿到请求数据后再操作的情况下使用。
执行下面的代码我们可以看到每等2秒会输出一个值,6秒后 三个数的和 和 第三个数几乎一起输出
1 | // 2s 之后返回双倍的值 |



