在描述Promise之前,先明确js中的异步概念,js代码在实际的执行中是单线程的,因此不存在异步的概念,但是浏览器不是单线程的,简单理解异步机制就是当代码中开启类似于setTimeout、ajax等异步任务时,浏览器会有一个单独的线程去记录这些异步任务,并把它们放入一个消息队列,当同步代码执行完成时会去调用消息队列里的异步任务
Promise的出现,最为主要的是为了解决回调地狱的问题,它的基本实现还是基于回调方法,本文主要记录Promise的日常使用,后续文章会记录Promise的实现原理
常用的两种使用方式:
1.不需要异步任务嵌套时
new Promise((resolve,reject) => {
if(true){
//异步任务成功
resolve('success')
}else{
//异步任务失败(主动调用reject或者发生异常,后面的then中都可以触发reject)
reject(new Error('reject'))
}
}).then((val) => {
//执行成功的后续代码
}, (error) => {
//执行失败的后续代码
})
2.需要嵌套时,也就是Promise的优点,链式调用!!!
//普通的异步回调嵌套,会出现如下种类的代码
ajax('').then(
ajax('').then(
...
)
)
//使用Promise
new Promise((resolve, reject) => {
//异步任务代码、
}).then((val) => {
console.log(val)
//默认返回一个新的Promise对象,也可手动返回
return new Promise(() => {
//下一个异步任务代码
})
}).then((val) => {
//如果上一层then中直接返回了一个变量,则作为参数传入,可在这里获取到
//这里处理上一个then中返回的Promise对象成功的后续代码
}).catch((error) => {
//可以使用catch统一捕获异常,因为从第一个Promise对象的执行结果会被逐级返回
//catch相当于别名的then,参数是(undefined,(err)=> {})
})
3.Promise的常用API(all,race)
let promiseA = new Promise((resolve, reject) => {
//异步任务代码
})
let promiseB = new Promise((resolve, reject) => {
//异步任务代码
})
//Promise.all
var promise = Promise.all([
promiseA,
promiseB
])
promise.then((val) => {
//全部完成才会进入这里
}).catch((error) => {
})
//Promise.race
var promise = Promise.race([
promiseA,
promiseB
])
promise.then((val) => {
//全部完成才会进入这里
}).catch((error) => {
})
4.Promise执行时序
正常的异步任务都是一个宏任务,但是Promise对象在js中是微任务,因此Promise的回调会在同步代码执行后立即执行
console.log('aaaaaa')
setTimeout(() => {
console.log('bbbbbb')
}, 0);
new Promise((resolve, reject) => {
console.log('cccccc');
resolve();
}).then((val) => {
console.log('dddddd')
})
console.log('eeeeee')
//输出如下
aaaaaa
cccccc
eeeeee
dddddd
bbbbbb