Promise
一、为什么需要Promise
需求:通过ajax请求id,再通过id请求用户名,再根据用户名获取用户的联系方式
//回调地狱:在回调函数中再进行函数的嵌套会导致格式不断缩进,这种代码不利于维护和降低了代码的可读性。
$.ajax({
type: 'GET',
url: './hasId.json',
success: function (res) {
const {
id
} = res //对象的解构赋值
console.log(id)
$.ajax({
type: 'GET',
url: './hasUserName.json',
data: {
id
},
success: function (res) {
const {
userName
} = res
console.log(res)
$.ajax({
type: 'GET',
url: './hasUserPhone.json',
data: {
userName
},
success: function (res) {
console.log(res)
}
})
}
})
}
})
Promise的出现就是为了解决回调地狱的问题。
二、Promise的基本使用
Promise本质是一个构造函数,可以通过 “new”关键字实例化对象
- 基础语法:
let promise = new Promise((resolve,reject)=>{})
- Promise接受一个函数作为参数;
- 再这个函数中可以接受两个参数resolve和rejected:
- resolve:如果任务成功完成并带有结果 value。
- reject:如果出现了 error,error 即为 error 对象。
- Promise实例属性:
- state:状态
- pending:准备、待解决、进行中,promise状态的初始值
- fulfilled:成功、已完成, 当resolve被调用的时候state转换为fulfilled;
- rejected:失败、已拒绝,当reject被调用时state转换为rejected;
- result:结果,最初是 undefined,然后在 resolve(value) 被调用时变为 value,或者在 reject(error) 被调用时变为 error;
- Promise状态的改变:
通过调用resolve或reject来转变Promise状态
let promise = new Promise((resolve,reject)=>{
resolve() //调用resolve函数使当前promise状态改变为fulfilled
})
console.log(promise) //fulfilled
let promise1 = new Promise((resolve,reject)=>{
reject() //调用resolve函数使当前promise状态改变为rejected
})
console.log(promise1) //rejected
注意: Promise状态的改变是一次性的,这就意味着当状态改变完成后不可再更改。
- Promise的结果
let promise = new Promise((resolve,reject)=>{
resolve("成功的结果") //调用resolve函数传递参数改变当前promise的结果
})
console.log(promise) //成功的结果
let promise1 = new Promise((resolve,reject)=>{
reject("失败的错误") //调用reject函数传递参数改变当前promise的结果,此时控制台会报错无信息 Uncatch(in promise)
})
console.log(promise1) //失败的错误
三、 Promise 的方法
- then()方法:
let promise = new Promise((resolve,reject)=>{
resolve("成功的结果") //调用resolve函数传递参数改变当前promise的结果
})
promise.then((res)=>{
console.log(res) //成功的结果
})
let promise2 = new Promise((resolve, reject) => {
reject("error") //调用resolve函数传递参数改变当前promise的结果
})
promise2.then(
(res) => {
console.log(res) //不执行
},
(error) => {
console.log(error) //error
})
-
then()方法的参数:then()方法接受两个回调函数作为参数,当Promise状态为fulfilled时则执行第一个回调函数,反之执行第二个。如果我们只对成功状态的情况感兴趣则可以只传一个参数。
-
then()方法中可以通过形参的形式来使用Promise对象的结果。
-
then()方法的返回值为一个promise对象
let promise = new Promise((resolve,reject)=>{
resolve("成功的结果") //调用resolve函数传递参数改变当前promise的结果
})
let result = promise.then((res)=>{
console.log(res) //成功的结果
})
console.log(result)
上述代码的执行结果如下:
then()方法返回值状态的改变:
注意: Promise中的状态不改变的话,then()方法中的回调不会执行。也就是说Promise的状态时pending时,则不会执行then()方法。
let promise = new Promise((resolve, reject) => {
resolve("成功的结果") //调用resolve函数传递参数改变当前promise的结果
})
let result = promise.then((res) => {
console.log(res) //成功的结果
return new Promise((resolve, reject) => {
resolve("111")
}) //可以通过return关键字改变then()方法返回值的状态为fulfilled,该回调中的代码有错时,then()方法的返回值状态会变成rejected
})
result.then((res) => {
console.log(res) // 111
})
console.log(result) //状态为fulfilled,结果为111
我们可以通过return一个新的Promise实例实现Promise的链式调用
- catch()方法
执行时机:
- 当Promise状态为rejected时被执行
let promise = new Promise((reslove,reject)=>{
reject()
})
promise.catch(()=>{
console.log('error') //会被执行
})
- 当Promise执行体中出现代码错误时,catch()方法会被执行
let promise = new Promise((reslove,reject)=>{
console.log(a)
})
promise.catch((reason)=>{
console.log('错误原因:',reason) //会被执行
})
上述代码执行结果如下:
- finally()方法
使用:不论Promise实例化对象的状态如何,该方法都会被执行。同时该方法会将Promise的结果和错误传递下去。
// 将Promise的结果传递给then()
new Promise((resolve, reject) => {
setTimeout(() => resolve("result"), 2000)
})
.finally(() => alert("Promise ready"))
.then(result => alert(result)); // <-- .then 对结果进行处理
//将Promise的错误传递给catch()
new Promise((resolve, reject) => {
throw new Error("error");
})
.finally(() => alert("Promise ready"))
.catch(err => alert(err)); // <-- .catch 对 error 对象进行处理
- 其他方法:
- Promise.all() : 返回一个Promise对象,参数是一个可迭代的对象,只有迭代中的所有promise都成功,结果才成功,有一个失败则结果为失败;
- Promise.race():race是赛跑的意思,它的参数和上述方法一样,参数中那个promise最先完成,则返回最先完成的那个promise的状态;