Promise 是什么?
- promise 是 JS 中进行异步编程的新的解决方案
- promise 是一个构造函数
为什么要用 Promise?
- 指定回调函数的方式更加灵活
- 支持链式调用, 可以解决回调地狱问题
什么是回调地狱?
回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件
回调地狱的缺点?
不便于代码阅读, 不便于异常处理
解决方案?
promise 链式调用
Promise 的状态
实例对象的一个属性PromiseState , 有以下三个值:
- pending 未决定的
- resolved / fullfilled 成功
- rejected / 失败
Promise 的状态改变
- pending 变为 resolved
- pending 变为 rejected
只有这2中情况, 且一个promise对象只能改变一次, 无论变为成功还是失败, 都会只有一个结果数据, 成功的结果数据一般称为 value, 失败的结果数据一般称为 reason.
Promise 对象的值
实例对象中的另一个属性PromiseResult
保存着异步任务(成功/失败)的结果
Promise 的API
1. Promise.then方法: (onResolved, onRejected) => {}
onResolved 函数: 成功的回调函数 (value) => {}
onRejected 函数: 失败的回调函数 (reason) => {}
2.Promise.catch方法:(onRejected) => {}onRejected 函数: 失败的回调函数 (reason) => {} 3.Promise.resolve方法:(value) => {}value: 成功的数据或 promise 对象
说明: 返回一个成功/失败的 promise 对象
// 如果传入的参数为非Promise类型的对象, 则返回的结果为成功promise对象
// 如果传入的参数为 Promise对象, 则参数的结果决定了 resolve 的结果
let p1 = Promise.resolve(123)
let p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('ok')
reject('error')
}))
console.log(p2)
p2.catch(reason => {
console.log(reason)
})
4. Promise.reject方法: (value) => {}
返回一个失败的 promise 对象
let p1 = Promise.reject(123)
console.log(p1)
// 无论传入任何类型的参数, 返回的始终是一个失败的 promise 对象
5. Promise.all方法: (promise) => {}
promise: 包含 n 个promise的数组
返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败
let p1 = new Promise((resolve, reject) => {
resolve('ok')
})
let p2 = Promise.resolve(123)
//let p3 = Promise.resolve('success')
let p3 = Promise.reject('error')
const result = Promise.all([p1, p2, p3])
console.log(result)
6. Promise.race方法: (promise) => {}
promise: 包含 n 个 promise 的数组
返回一个新的 promise, 第一个完成的promise的结果状态就是最终的结果状态
let p1 = new Promise((resolve, reject) => {
// resolve('ok')
setTimeout(() => {
resolve('ok')
}, 1000)
})
let p2 = Promise.resolve(123)
//let p3 = Promise.resolve('success')
let p3 = Promise.reject('error')
const result = Promise.race([p1, p2, p3])
console.log(result)
Promise 的一些关键问题
1. 如何改变promise的状态
- resolve(value): 如果当前是pending就会变成resolved
- reject(reason): 如果当前是pending就会变成rejected
- 抛出异常: 如果当前是pending就会变为rejected
let p1 = new Promise((resolve, reject) => {
// 1. resolve()
resolve('ok') // pending => (resolved / fullfilled)
// 2. reject()
reject('error') // pending => rejected
// 抛出异常
throw '出问题了'
})
2. 一个promise指定多个成功/失败回调函数, 都会调用吗?
当promise改变为对应状态时都会调用
let p1 = new Promise((resolve, reject) => {
// 下面一行代码代表改变了状态, 如果把它注释掉, 下面两个then方法就不会被调用, 所以才说状态改变就会调用.
resolve('ok')
})
p1.then(value=> {
console.log(value)
})
p1.then(value=> {
alert(value)
})
3. promise.then()返回的新promise的结果状态由什么决定?
简单的说: 由then()指定的回调函数执行的结果决定
详细的说:
- 如果抛出异常, 新promise变为rejected, reason为抛出的异常
- 如果返回的时非promise的任意值, 新promise变为resolved, value为返回的值
- 如果返回的时一个新的promise, 此 promise的结果就会称为新promise的结果
let p = new Promise((resolve, reject) => {
resolve('success')
})
let result = p.then(value => {
//1. 抛出异常
throw '出来了问题'
// 2. 返回的结果时非 Promise 类型的对象
return 123
// 3, 返回的结果是 Promise 对象
return new Promise((resolve, reject) => {
// resolve('ok')
reject('error')
})
}, reason => {
console.warn(reason)
})
console.log(reasult)
4. Promise 如何串联多个操作任务?
- promise 的 then() 返回一个新的promise, 可以看成then()的链式调用
- 通过then的链式调用串联多个同步/异步任务
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok')
}, 1000)
})
p.then(value => {
return new Promise((resolve, reject) => {
resolve('success')
})
}).then(value => {
console.log(value)
// 打印出来的结果是 success
}).then(value => {
console.log(value)
// 打印出来的结果 undefined
})
5.Promise 的异常穿透?
- 当使用promise的then链式调用时, 可以在最后指定失败的回调
- 前面任何操作出了异常, 都会传到最后失败的回调中处理
let p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('ok')
reject('error')
}, 1000)
})
p.then(value => {
console.log('111')
// throw '错误了'
}).then(value => {
console.log('222')
}).then(value => {
console.log('333')
}).catch(reason => {
console.log(reason)
})
- 中断Promise链?
- 当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
- 方法: 在回调函数中返回一个pending状态的promise对象
let p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('ok')
reject('error')
}, 1000)
})
p.then(value => {
console.log('111')
// throw '错误了'
return new Promise(() => {})
}).then(value => {
console.log('222')
}).then(value => {
console.log('333')
}).catch(reason => {
console.log(reason)
})
async 与 await
- async 函数
- 函数的返回值为promise对象
- promise对象的结果由async函数执行的返回值决定
async function main() {
// 1. 返回值是一个非promise类型的数据
// return 123
// 2. 返回的是一个promise对象
return new Promise((resolve, reject) => {
// resolve('ok')
reject('error')
})
// 抛出异常
throw '错误了'
}
let result - main()
console.log(result)
- await 函数
- await 右侧的表达式一般为promise对象, 但也可以是其他的值
- 如果表达式是promise对象, await 返回的是 promise成功的值
- 如果表达式是其他值, 直接将此值作为await的返回值
注意
- await 必须写在 async 函数中, 但 async 函数中可以没有 await
- 如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch捕获处理
async function fn() {
let p = new Promise((resolve, reject) => {
// resolve('ok')
reject('error')
})
// 1. 右侧是promise的情况
// let res = await p;
// 2. 右侧是其他类型的数据
// let res = await 20
// 3. 如果 promise 是失败的状态
try {
let res = await p
} catch(e){
console.log(e)
}
console.log(res)
}