1.将 promise 封装到函数中
function fn() {
const p = new Promise(function (resolve, reject) {
const timer = Math.ceil(Math.random() * 3000)
console.log('班长, 去帮我买瓶水')
setTimeout(() => {
if (timer > 1500) {
console.log('买水失败, 用时: ', timer)
reject('买水失败是因为时间超过 1500 毫秒')
} else {
console.log('买水成功, 用时: ', timer)
resolve('买水成功是因为 时间小于 1500 毫秒')
}
}, timer)
})
return p
}
// 得到 fn 函数内部的 promise 对象
const res = fn()
// 普通调用
res.then(() => {
console.log('如果我这行内容打印, 说明 promise 的状态为 成功')
})
res.catch(() => {
console.log('如果我这行内容打印, 说明 promise 的状态为 失败')
})
// 链式调用
res.then((str) => {
console.log('如果我这行内容打印, 说明 promise 的状态为 成功', str)
}).catch((str) => {
console.log('如果我这行内容打印, 说明 promise 的状态为 失败', str)
})
function fn() {
const p = new Promise(function (resolve, reject) {
const timer = Math.ceil(Math.random() * 3000)
console.log('班长, 去帮我买瓶水')
setTimeout(() => {
if (timer > 1500) {
reject('超时, 所以买水失败')
} else {
resolve('没有超时, 买水成功')
}
}, timer)
})
return p
}
// 得到 fn 函数内部的 promise 对象
const res = fn()
/**
* 当你在第一个 then 里面 返回一个 新的 promise 对象
*
* 然后你可以在 第一个 then 的后面 再次书写一个 then
*/
// 链式调用
res.then((str) => {
console.log(`因为 ${str}, 所以奖励班长 10 个 bug`)
return fn()
}).then((str) => {
console.log('如果我输出了, 表示班长 第二次买水成功')
return fn()
}).then((str) => {
console.log('如果我输出了, 表示班长 第三次买水成功')
}).catch((str) => {
console.log(`如果我输出了, 说明之前某一次买水失败了`)
})
2.async 与 await
是 promise 的一种调用方案 (也就是说 必须结合着 promise 一起使用)
能够将 异步代码, 写的像 "同步代码一样
- async: 书写在 一个函数的 开头, 表明当前函数是一个异步函数, 内部可以书写 await
- await: 具有等待的含义, 书写在 异步函数 前, 代码运行到这个位置的时候, 会有一个等待效果
一直等到这个异步任务结束, 并且将异步任务的反馈结果 当一个值返回出来
function fn() {
const p = new Promise(function (resolve, reject) {
const timer = Math.ceil(Math.random() * 3000)
console.log('班长, 去帮我买瓶水')
setTimeout(() => {
if (timer > 5000) {
reject('超时, 所以买水失败')
} else {
resolve('没有超时, 买水成功')
}
}, timer)
})
return p
}
newFn()
async function newFn() {
// 因为函数开头写了 async, 所以这个函数就是一个独特的异步函数, 内部可以书写 await
// await 是等待的意思, 他必须等待后边的 promise 结束后再往下继续执行代码
const r1 = await fn()
console.log('第一次买水: ', r1)
const r2 = await fn()
console.log('第二次买水: ', r2)
const r3 = await fn()
console.log('第三次买水: ', r3)
}
3.async 与 await 的缺点
不能正常的捕获到 promise 的失败状态
-
- try...catch
-
- 封装一个永远不会失败的 promise 也就是说 不管请求状态如何, 永远调用 resolve 让 promise 的状态一定是成功
为了区分这次请求是成功还是失败, 我们不在单纯的返回一个字符串了
而是返回一个对象
注意: 这个对象 我们约定 里边有一个 code 属性, 成功时赋值为 1, 失败时赋值为 0
function fn() {
const p = new Promise(function (resolve, reject) {
const timer = Math.ceil(Math.random() * 3000)
console.log('班长, 去帮我买瓶水')
setTimeout(() => {
if (timer > 1500) {
// reject('超时, 所以买水失败')
resolve({
code: 0, // 代表当前请求失败
msg: '超时, 所以买水失败'
})
} else {
resolve({
code: 1, // 代表当前请求成功
msg: '没有超时, 买水成功'
})
}
}, timer)
})
return p
}
newFn()
// 解决缺点 方案2
async function newFn() {
const r1 = await fn()
if (r1.code === 0) {
console.log('请求失败的补救措施')
} else {
console.log('请求成功, 正常执行代码即可')
}
}
// newFn()
// 解决缺点 方案1
async function newFn() {
try {
const r1 = await fn()
console.log('第一次买水: ', r1)
} catch (error) {
console.log(error)
}
try {
const r1 = await fn()
console.log('第二次买水: ', r1)
} catch (error) {
console.log(error)
}
}
4.promise 的其他方法
function fn() {
const p = new Promise(function (resolve, reject) {
const timer = Math.ceil(Math.random() * 3000)
console.log('班长, 去帮我买瓶水')
setTimeout(() => {
if (timer > 1500) {
reject('超时, 所以买水失败')
} else {
resolve('没有超时, 买水成功')
}
}, timer)
})
return p
}
// 1. promise 对象上的方法
// const res = fn()
// res.then(() => {
// console.log('成功时执行')
// }).catch(() => {
// console.log('失败时执行')
// }).finally(() => {
// /**
// * 正常业务场景中, 我们再发起一个请求的时候, 会将页面弹出一个遮罩层
// * 然后再请求结束的时候 需要将这个遮罩层关闭
// * 这个时候如果放在 then 中 那么会有一个 问题, 就是请求失败的时候不会触发then
// * 所以我们一般不会放在 then 关闭遮罩层, 而是 放在 finally 中
// */
// console.log('每一次都会执行 (不会考虑成功还是失败)')
// })
// 2. promise 构造函数上的一些方法
// Promise.all([fn(), fn(), fn()]).then(() => {
// console.log('所有的 参数 全部都返回一个 成功状态的时候, 会执行')
// }).catch(() => {
// console.log('所有参数中, 有一个为失败状态, 就会执行 catch')
// })
Promise.race([fn(), fn(), fn()]).then(() => {
console.log('这些参数中, 结束最快的哪一个状态为 成功的时候执行')
}).catch(() => {
console.log('这些参数中, 结束最快的哪一个状态为 失败的时候执行')
})
function fn() {
const p = new Promise(function (resolve, reject) {
const timer = Math.ceil(Math.random() * 3000)
console.log('班长, 去帮我买瓶水')
setTimeout(() => {
if (timer > 1500) {
reject('超时, 所以买水失败')
} else {
resolve('没有超时, 买水成功')
}
}, timer)
})
return p
}
// Promise.allSettled([fn(), fn(), fn()]).then((res) => {
// /**
// * 在数组内传递的 promise 全都执行完毕后, 返回一个数组给到 then 函数
// *
// * 数组内的对象就是我们传递进来的 promise 对象的执行结果
// */
// console.log(res)
// })
Promise.resolve().then(() => {
console.log('强制返回一个 状态为 成功的 promise')
})
Promise.reject().then(() => {
console.log('如果我打印了, 说明 当前的 promise 状态为成功')
}).catch(() => {
console.log('强制返回一个 状态为 失败的 promise 对象')
})