Appearance
Promise
Promise 的意义 - Promise 是异步编程的一种解决方案,是一个对象,通过它可以获取异步操作的消息
Promise 对象有以下特点
对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
一旦状态改变,就不会再次改变 (Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。)
任何时候都可以得到结果
缺点
- 无法取消 Promise
一旦新建它就会立即执行,无法中途取消。
js
const promise = new Promise(function (resolve, reject) {
// 这边会立即执行,而不像回调函数 这是一个函数 需要调用一下,当然也可以变成自执行函数
if (true) {
resolve(value)
} else {
reject(error)
}
})
- 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
js
try {
const promise = new Promise(function (resolve, reject) {
// 这边会立即执行,而不像回调函数 这是一个函数 需要调用一下,当然也可以变成自执行函数
throw new Error("这是错误")
}).catch(error => {
console.log(`promise catch error : `, error)
})
} catch (error) {
console.log(`外部捕获`, error) //不会执行,只能通过 promise.catch()
}
- 当处于 pending 状态时,无法得知目前进展到哪一个阶段
这就是所这有三种状态 没有中间的状态了
什么是回调地狱? Promise 如何解决回调地狱?
回调地狱 - 如果我们在回调内部存在另外一个异步操作,即出现多层嵌套问题,导致变成一段混乱且不可读的代码,此代码就称为'回调地狱'
多层嵌套问题 每种任务的处理结果存在两种可能性(成功或失败),那么需要在每种任务执行结束后分别处理这两种可能性
这两个问题在回调函数中尤为突出,Promise 的诞生就是为了解决这两个问题
Promise 解决'回调地狱'
- 回调函数延迟绑定
js
const promise1 = new Promise(function (resolve, reject) {
// 这边会立即执行,而不像回调函数 这是一个函数 需要调用一下,当然也可以变成自执行函数
throw new Error("这是错误")
// 延迟绑定回调函数
})
.then(res => {
return Promise.reject(`内部第二个promise的error`)
})
.catch(err => {
console.log(`promise catch error : `, err)
})
- 返回值穿透
js
const promise1 = new Promise(function (resolve, reject) {
// 这边会立即执行,而不像回调函数 这是一个函数 需要调用一下,当然也可以变成自执行函数
resolve(1)
// 延迟绑定回调函数
})
.then(res => {
console.log(res)
return Promise.resolve(`内部第二个promise`)
})
.then(res => {
console.log(res)
return Promise.reject(`内部第二个promise err`)
})
.catch(err => {
console.log(`promise catch error : `, err)
})
- 错误冒泡
Promise.then()
- then 方法返回的是一个新的 Promise 实例(注意,不是原来那个 Promise 实例)。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。
js
const promise1 = new Promise(function (resolve, reject) {
// 这边会立即执行,而不像回调函数 这是一个函数 需要调用一下,当然也可以变成自执行函数
resolve(1)
// 延迟绑定回调函数
})
.then(res => {
console.log(res)
return Promise.resolve(`内部第二个promise`)
})
.then(res => {
console.log(res)
return Promise.reject(`内部第二个promise err`)
})
.catch(err => {
console.log(`promise catch error : `, err)
})
Promise 主体中返回一个 字符串是不会向下执行的
如果 then 中的回调函数又返回(return),那么 then 返回的 Promise 就会变成接受状态(resolved),并且将返回的值作为接受状态的回调函数的参数值
如果 then 中的回调函数抛出一个错误,那么 then 返回的 Promise 将会成为拒绝状态(rejected),并且将抛出的错误作为拒绝状态的回调函数的参数值(后面的 then 也不会再执行)
如果 then 中的回调函数返回一个**未定状态(pending)**的 Promise,那么 then 返回的 Promise 也是未定状态,并且它的最终状态会与那个 Promise 的最终状态相同,同时,它变为终态时调用的回调函数的参数值与那个 Promise 变为终态时的回调函数的参数值相同
js
new Promise(function (resolve, reject) {
return "字符串的值"
})
.then(res => {
console.log(res) //不会执行
})
.catch(error => {
console.log(`promise catch error : `, error)
})
new Promise(function (resolve, reject) {
resolve(1)
})
.then(res => {
console.log(res) // 1
return "这是then返回的,而不是primise中返回的"
})
.then(res => {
console.log(res) // 这是then返回的,而不是primise中返回的
return
})
.then(res => {
console.log(res) // 打印的是undefined
return new Promise(function (resolve, reject) {
setTimeout(() => {
resolve("3s resolve")
}, 3000)
})
})
.then(res => {
console.log(res) // 3s 才会打印 '3s resolve'
throw new Error(`这是then中的错误`)
})
.then(res => {
console.log("还会执行么?") // 不会再执行了
})
.catch(error => {
console.log(`promise catch error : `, error)
})
题目
- 题 1
js
const log = s => {
console.log(s)
}
log(1)
new Promise(resolve => {
resolve(2)
}).then(v => {
log(v)
})
async function fn1() {
log(3)
}
async function fn2() {
log(4)
await fn1()
log(5)
}
fn2()
结果为: 14325
Promise.all
Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。
全部正常
js
const promise1 = Promise.resolve(1)
const promise2 = 2
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 3)
})
Promise.all([promise1, promise2, promise3]).then(values => {
console.log(values)
})
// 结果为 : Array [1, 2, 3]
第一个失败的原因
js
const promise1 = Promise.resolve(1)
const promise2 = Promise.reject(2)
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 3)
})
Promise.all([promise1, promise2, promise3]).then(err => {
console.log(values)
})
// 结果为 : 2
Promise.allSettled
Promise.allsettled(iterable) 方法方法返回一个在所有给定的 promise 已被决议或被拒绝后决议的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果
全部正常
js
const promise1 = Promise.resolve(1)
const promise2 = 2
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 3)
})
Promise.allsettled([promise1, promise2, promise3]).then(values => {
console.log(values)
})
// 结果为 : Array [1, 2, 3]
有失败也会全部返回
js
const promise1 = Promise.resolve(1)
const promise2 = Promise.reject("err 2")
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 3)
})
Promise.allsettled([promise1, promise2, promise3]).then(err => {
console.log(values)
})
// 结果为 : [1,"err 2",3]
Promise.any()
Promise.any() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。
只要有一个正常,就返回第一个正常的结果
js
const promise1 = Promise.resolve(1)
const promise2 = Promise.reject("err 2")
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 3)
})
Promise.allsettled([promise1, promise2, promise3]).then(values => {
console.log(values)
})
// 结果为 : 1
全部失败才会返回所有的失败原因
js
const promise2 = Promise.reject("err 2")
const promise3 = new Promise((resolve, reject) => {
setTimeout(reject, 100, "err 3")
})
Promise.allsettled([promise2, promise3]).then(err => {
console.log(values)
})
// 结果为 : ["err 2","err 3"]
Promise.race()
返回第一个 履行或拒绝 的结果