一. 前言
在如今前后端分离盛行的时代,异步尤为重要,而用于解决异步问题的promise与async/await同样成为了es6中非常重要的内容.
二. 异步
let a = 0
setTimeout(() => {
a = 1
}, 1000)
console.log(a) // 0
此时这个延迟就成为异步执行的了,a值还没有变1就被使用输出,我们只能得到0。
三. Promise
有时候我们不得不进行异步操作,比如从后台请求数据,我们需要时间,等待它得到数据后再使用。
也就是我们希望异步内容也能够类似同步一样。
Promise就是一种es6出现的异步解决方案。
Promise基本使用
- new Promise()内接收一个函数,参数为
resolve,reject - Promise内的函数将可以执行任意时长,执行到调用
resolve()或reject(),我们此处把它放在延迟1s后执行,此时a已经被赋值为1,因此就可以得到被赋值后的a。 resolve()进入.then也就是执行成功回调,reject()进入.catch也就是手动执行错误进入捕获异常,reject()用的较少。
let a = 0
new Promise((resolve, reject) => {
setTimeout(() => {
a = 1
resolve()
}, 1000)
})
.then(() => {
console.log(a) //1
})
.catch(() => {})
Promise回调可接受入参
.then中的回调函数可以存在入参,入参为resolve()手动传入,此处res便是传入的a值。.catch与reject()的关系与上面两者同理,只不过变成了手动捕捉错误时的回调。
let a = 0
new Promise((resolve, reject) => {
setTimeout(() => {
a = 1
resolve(a)
}, 1000)
})
.then((res) => {
console.log(res) //1
})
.catch(() => {})
Promise可进行连续回调
- 第一种方式,回调函数中接受返回一个新的Promise进行下一步回调。
- 第二种方式,
Promise.resolve(res)在res为普通数据时等同于new Promise并且resolve(res) - 第三种也是最常用的,再异步回调中直接返回普通数据也可当作接受了一个新的Promise进行下一步回调
let a = 0
new Promise((resolve, reject) => {
setTimeout(() => {
a = 1
resolve(a)
}, 1000)
})
.then((res) => {
return new Promise((resolve, reject) => {
resolve(res)
})
//等同于
//return Promise.resolve(res)
//等同于
//return res
})
.then((res) => {
console.log(res) //1
})
.catch(() => {})
四. async/await
Promise的链式调用也解决了过去异步请求回调地狱的问题。
并且Promise提供了一种新的更优雅的异步编程方式,结合async/await,可以将Promise的链式调用变为类似同步代码的形式。
async/await有一个限制就是必须在函数中使用,因此我们将代码包进一个函数,并在函数前加上async,这样我们便可以在函数中使用await关键字。
const test = async () => {
let a = 0
...
}
test()
await用在哪里呢?用在.then回调前的Promise
await后面跟着Promise,而它的返回值便是回调时resolve()传来的值,代替了回调函数,看起来代码一下子就清晰很多了。
const test = async () => {
let a = 0
const res = await new Promise((resolve, reject) => {
setTimeout(() => {
a = 1
resolve(a)
}, 1000)
})
console.log(res) //1
}
test()