promise原理与async 及 await
-
-
- 1.1 Promise是一个构造函数
- 1.2 Promise优缺点
- 1.3 async 及 await
- 1.4 相较于 Promise,async/await有何优势?
-
1.1 Promise是一个构造函数
1 Promise 是一个构造函数
我们可以创建 Promise 的实例 const p = new Promise()
new 出来的 Promise 实例对象,代表一个异步操作
2 Promise.prototype 上包含一个 .then() 方法
每一次 new Promise() 构造函数得到的实例对象,
都可以通过原型链的方式访问到 .then() 方法,例如 p.then()
3 .then() 方法用来预先指定成功和失败的回调函数
p.then(成功的回调函数,失败的回调函数)
p.then(result => { }, error => { })
调用 .then() 方法时,成功的回调函数是必选的、失败的回调函数是可选的
1.2 Promise优缺点
缺点
无法取消
Promise
,错误需要通过回调函数捕获。优点
1、当我们在构造
Promise
的时候,构造函数内部的代码是立即执行的(见下面的代码),而返回的结果是异步的Promise2、Promise`的三种状态分别是:等待中(pending)、完成了 (resolved)、拒绝了(rejected),承诺一旦从等待状态变成为其他状态就永远不能更改状态了,也就是说一旦状态变为 resolved 后,就不能再次改变
//当我们在构造 Promise的时候,构造函数内部( new Promise)的代码是立即执行的
new Promise((resolve, reject) => {
console.log('new Promise')
resolve('success')
}).then(console.log('resolve'))
console.log('finifsh')
//结果 new Promise -> resolve->finifshasync function fn () {
console.log('嘿嘿')
const res = await fn2()
console.log(res)// 注意*****微任务,最后输出
}
async function fn2 () {
console.log('gaga')
}
fn()
console.log(222)
//嘿嘿->gaga->222->undefine
3、
Promise
实现了链式调用,也就是说每次调用 then
之后返回的都是一个 Promise
,并且是一个全新的 Promise
,原因也是因为状态不可变。如果你在 then
中 使用了 return
,那么 return
的值会被 Promise.resolve()
包装(也是‘缺点’)Promise.resolve(1)
.then(res => {
console.log(res) // => 1
return 2 // 包装成 Promise.resolve(2)
})
.then(res => {
console.log(res) // => 2
})
文章图片
注意:上述的代码无法保证文件的读取顺序,需要做进一步的改进!
文章图片
1.3 async 及 await
【javascript|promise原理与async 及 await】一个函数如果加上
async
,那么该函数就会返回一个 Promise
;async
就是将函数返回值使用 Promise.resolve()
包裹了下,和 then
中处理返回值一样,并且 await
只能配套 async
使用;因为
await
将异步代码改造成了同步代码(有顺序),如果多个异步代码没有依赖性却使用了 await
会导致性能上的降低。async关键字
- async关键字用于声明?个异步函数(如 async function asyncTask1() {…})
- async会?动将常规函数转换成 Promise,返回值也是?个 Promise对象
- async函数内部可以使? await
- await用于等待异步的功能执?完毕 var result = await someAsyncCall()
- await放置在 Promise调?之前,会强制async函数中其他代码等待(awiat之后的代码是异步微任务),直到 Promise完成并返回结果
- await只能在 async函数内部使?
async function test() {
// 以下代码没有依赖性的话,完全可以使用 Promise.all 的方式
// 如果有依赖性的话,其实就是解决回调地狱的例子了
await fetch(url)
await fetch(url1)
await fetch(url2)
}
//案例
let a = 0
let b = async () => {
a = a + await 10
console.log('2', a) // -> '2' 10
}
b()
a++
console.log('1', a) // -> '1' 1//输出顺序:1 1->2 10let a = 0
let b = async () => {
a = a + await 10
console.log('2', a) // -> '2' 10
}
b().then(console.log('3', a))
a++
console.log('1', a) // -> '1' 1//输出顺序:3 0 ->1 1->2 10
//await之后才是微任务
//这里3 0在最前面,表明B直接调用了promise的then原型,a=0
- 首先函数
b
先执行,在执行到await 10
之前变量a
还是 0,因为await
内部实现了generator
,generator
会保留堆栈中东西,所以这时候a = 0
被保存了下来 - 因为
await
是异步操作,后来的表达式不返回Promise
的话,就会包装成Promise.reslove(返回值)
,然后会去执行函数外的同步代码 - 同步代码执行完毕后开始执行异步代码,将保存下来的值拿出来使用,这时候
a = 0 + 10
await
内部实现了 generator
,其实 await
就是 generator
加上 Promise
的语法糖,且内部实现了自动执行 generator
。1.4 相较于 Promise,async/await有何优势?
1.同步化代码的阅读体验(Promise虽然摆脱了回调地狱,但 then链式调?的阅读负担还是存在的)
2.和同步代码更一致的错误处理方式( async/await可以?成熟的 try/catch做处理,比 Promise的
错误捕获更简洁直观)
3.调试时的阅读性,也相对更友好
推荐阅读
- React|React UI组件库——如何快速实现antd的按需引入和自定义主题
- React|【React路由】编程式路由导航和withRouter的使用——push / replace
- React|React路由组件传参的三种方式——params、search、state
- React|【React组件】github搜索案例之 父子组件通信 (附源码)
- React|【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- React|【ReactRouter5】路由的模糊匹配,重定向以及嵌套路由
- React|【React】深入理解React组件生命周期----图文详解(含代码)
- echarts|CMS项目数据可视化-echarts的使用
- React|Vscode中快速生成代码的方式