Promise的基础概念
Promise在js当中,是异步编程的一种解决方案。Promise对象封装一个异步操作并获取其成功失败的返回值,通过resolve/reject这两个方法来处理成功与失败(例如:网络请求,定时器,数据库操作等)。
示例:
js
let p = new Promise((resolve, reject) => {
resolve("你好,promise")
})
p.then(
(value) => {
console.log(value, "===value===")
},
(error) => {
console.log(error, "===error===")
}
)
//结果打印:你好,promise
为什么要使用Promise呢?
在开发当中我们接触的异步编程不在少数,而我们常见的网络请求和定时器都离不来异步操作,早期一般会通过回调函数来解决这类问题,但是我们常常会遇到几个网络请求相互联系,如果使用回调函数一步步的回调操作,很容易就会产生回调地狱问题,一旦业务过于复杂或者长期迭代,代码就会十分用臃肿,难以维护。正是Promise的横空出世才解决地狱回调的问题。
Promise的状态属性
Promise有三种状态,分别是pending,fulfilled,rejected。下面我们一一了解。
pending:进行中,等待的状态
在没有遇到(resolve,reject)之前,Promise将一直处于pending状态。其状态只能改变一次,一般来说只能由进行中变成成功/失败(pending-->fulfilled/rejected),不能由成功变成失败,或者失败变成成功,如果看见状态一直处于pending时,说明Promise对象当前的状态并没有被是Promise的执行器函数resolve/reject改变。
js
let p = new Promise((resolve, reject) => {})
console.log(p, "===p===")
fulfilled:成功状态
Promise对象通过resolve将Promise的状态由pending改变成fulfilled。
js
let p = new Promise((resolve, reject) => {
resolve("wow!")
})
console.log(p, "===p===")
rejected:失败状态
Promise对象通过reject将Promise的状态由pending改变成rejected。
js
let p = new Promise((resolve, reject) => {
reject("wuwuwu!")
})
console.log(p, "===p===")
Promise的工作流程
首先通过new创建一个新的Promise对象,此时Promise的状态是处于pending状态。然后执行异步操作,执行resolve或者reject方法,将pending状态变成成功或者失败(fulfilled/rejected)的状态。如果我们执行resolve()将状态从pending变成fulfilled时,调用Promise实例上的then方法,执行then方法中第一个参数(成功的回调函数)的方法,最后抛出一个新的Promise对象;相反,如果我们执行reject()将状态从pending变成rejected时,我们可以通过Promise实例上的then方法(失败的的回调函数)或者catch方法返回一个新的Promise对象。
Promise的方法
1.Promise.resolve()
Promise.resolve() 静态方法接收一个值,返回一个成功或者失败的Promise对象,它的作用就是快速得到一个Promise对象。Promise.resolve()
实际上相当于 new Promise((resolve) => resolve(value))
的简写。传入的值如果为一个非Promise的值,会返回成功的状态,传入的值如果是Promise对象,则返回值的状态要根据传入的Promise对象的状态来决定。
js
let p = Promise.resolve("ok")
let p1 = Promise.resolve(
new Promise((resolve, reject) => {
resolve("成功了")
})
)
let p2 = Promise.resolve(
new Promise((resolve, reject) => {
reject("失败了")
})
)
console.log(p, "=====非Promise====")
console.log(p1, "=====resolve====")
console.log(p2, "=====reject====")
//爆红是因为失败了,用catch接收一下就可以了
2.Promise.reject()
Promise.reject()静态返回一个失败的Promise对象,不管传入的值是非Promise对象还是Promise对象,返回的一直都是失败的Promise对象。
js
let p = Promise.reject("非Promise对象")
let p1 = Promise.reject(
new Promise((resolve, reject) => {
resolve("失败了吗")
})
)
let p2 = Promise.reject(
new Promise((resolve, reject) => {
reject("失败了吗")
})
)
console.log(p, p1, p2)
3.Promise.all()
Promise.all()静态方法的参数一般为Promise组成的一个数组,并且传入数组的的Promise都为成功的状态时才能成功的返回一个成功的Promise对象。如果传入数组中有一个失败,返回的结果就是我们传入数组中失败的Promise的结果。
js
let p1 = Promise.resolve("1")
let p2 = Promise.reject("2")
let p3 = Promise.resolve(
new Promise((resolve, reject) => {
resolve("3")
})
)
let p4 = Promise.resolve(Promise.resolve("4"))
let result1 = Promise.all([p1, p2, p3])
let result2 = Promise.all([p1, p3, p4])
console.log(result1, result2)
4.Promise.race()
Promise.race()方法的参数一般也是Promise组成的一个数组,最终返回一个新的Promise对象。与Promise.all()不同的是,它是根据传入数组的第一个Promise对象的结果状态来改变。
js
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("ok")
}, 1000)
})
let p2 = Promise.reject("2")
let p3 = Promise.resolve(
new Promise((resolve, reject) => {
resolve("3")
})
)
let result1 = Promise.race([p1, p2, p3])
let result2 = Promise.race([p3, p2, p1])
console.log(result1, result2)
Async/Await
async/await也是一套关于异步的解决方案,是基于Promise的二次封装的语法糖。两者相比较而言,async/await更加的简洁明了。两者区别在于Promise返回的结果通常需要用then来接收返回值,而async/await直接在函数体内就可以处理结果。深层次的使用Promise可能也会导致回调地狱,而async/await提供了类似同步代码结构,更易维护。两者相比async/await更加优雅,注意一点await只能用在async标记的函数内使用。
js
const handleCallBack = () => {
return new Promise((resolve, reject) => {
if (Math.floor(Math.random() * 10 + 1) > 5) {
resolve("我大于5")
} else {
reject("我小于等于5")
}
})
}
//Promise
handleCallBack()
.then((value) => {
console.log(value, "====Promise方式==成功==")
})
.catch((error) => {
console.log(error, "====Promise方式==失败==")
})
// async/await
async function handleAsync() {
try {
let data = await handleCallBack()
console.log(data, "====async/await方式==成功==")
} catch (error) {
console.log(error, "====async/await方式==失败==")
}
}
handleAsync()