什么是Promise?
Promise是异步编程的一种解决方案,在ES6中被统一规范,其实是一个构造函数
回调地狱
回调地狱(Callback Hell)是异步编程中经常遇到的一个问题,特别是在使用大量嵌套回调函数时。当你需要在一个异步操作完成后执行另一个异步操作,而这些操作又依赖于前一个操作的结果时,很容易就会出现多层嵌套的回调函数,这种代码结构就被称为回调地狱。而Promise就是解决回调地狱的一种方案
需求:
通过AJAX请求id ,再根据id请求用户名.再根据用户名,再根据用户名获取email
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="JQuery.js"></script>
<script>
// 拿到a的数据后才去请求b,拿到b的数据后再去请求c 这就叫回调地狱
// 像这种回调嵌套回调的写法就叫回调地狱
$.ajax({
method: "get",
url: "data.json",
success(res) {
console.log(res);
$.ajax({
method: "get",
url: "data2.json",
success(res) {
console.log(res);
$.ajax({
method: "get",
url: "data3.json",
success(res) {
console.log(res);
},
});
},
});
},
});
</script>
</body>
</html>
Promise的基本使用
Promise是一个构造函数,通过new关键字实例化对象
语法:
new promise((resolve, reject)=>{})
- promise接受一个函数作为参数
- 在参数函数中接受两个参数
- resolve:成功函数
- reject:失败函数
- promise实例有两个属性
- 状态(State)
- 结果(Result)
Promise状态
- 一个
Promise
有三种状态:pending
(进行中)fulfilled
(已成功)rejected
(已失败)。Promise
的状态一旦从pending
变为fulfilled
或rejected
,就不可再变,是一次性的。- 通过调用resolve()和reject()改变当前Promise对象的状态
示例1:使状态变为fulfilled
const p = new Promise((resolve, reject) => {
// resolve(): 调用函数, 使当前Promise对象的状态改成fulfilled
resolve();
})
console.dir(p) // fulfilled
示例2:使状态变为rejected
const p = new Promise((resolve, reject) => {
// reject(): 调用函数, 使当前Promise对象的状态改成rejected
reject()
})
console.dir(p)
promise结果
- 当
Promise
状态变为fulfilled
时,它会带有一个结果值;- 当状态变为
rejected
时,它会带有一个拒绝原因(即错误)。
示例:
const p = new Promise((resolve, reject) => {
// 通过调用 resolve,传递参数,改变 当前Promise对象的结果
resolve("成功的结果");
// resolve();
// reject("失败的结果")
})
console.dir(p)
promise的方法
1)then方法
参数:两个参数均是函数
- 函数1:当promise状态是fulfilled时执行
- 函数1:当promise状态是rejected时执行
返回值:是一个promise对象
示例:
const p = new Promise((resolve, reject) => {
// 通过调用 resolve,传递参数,改变 当前Promise对象的结果
// resolve(123);
reject("失败的结果")
})
//then方法函数
// - 参数
// 两个参数都是函数
// 返回值: 是一个Promise对象
p.then(()=>{
//当Promise的状态使fulfilled时执行
console.log("成功的回调",value)
},()=>{
// 当Promise的状态时rejected时, 执行
console.log("失败时调用",err)
})
console.dir(p)
then参数函数中使用形参可以使用promise对象的结果
示例:
const p = new Promise((resolve, reject) => {
// 通过调用 resolve,传递参数,改变 当前Promise对象的结果
// resolve(123);
reject("失败的结果")
})
// then方法函数
// 参数
// 两个参数都是函数
// 返回值: 是一个Promise对象
p.then((value)=>{
//当Promise的状态使fulfilled时执行
console.log("成功的回调",value)
},(err)=>{
// 当Promise的状态时rejected时, 执行
console.log("失败时调用",err)
})
console.dir(p)
then方法返回一个新的Promise实例,状态时pending
也就是链式操作
new Promise((resolve, reject) => {}.then().then()
示例:
const p = new Promise((resolve, reject) => {
resolve(123)
})
const t = p.then.((value) => {
console.log("成功")
},(reason) => {
console.log("失败")
})
console.dir(t)
})
promise的状态不改变,不会执行then里的方法
示例:
// 如果Promise的状态不改变,then里的方法不会执行
new Promise((resolve, reject) => {
}).then.((value) => {
console.log("成功")
},(reason) => {
console.log("失败")
})
在then方法中,通过return将返回的Promise实例改为fulfilled状态,并return的数据会被下一个then方法的形参接收
示例:
// 如果Promise的状态改变,then里的方法不会执行
const p = new Promise((resolve, reject) => {
resolve()
})
const t = p.then((value) => {
console.log("成功")
// 使用return可以将t实例的状态改为fulfilled
return 123
},(reason) => {
console.log("失败")
})
t.then.((value) => {
console.log("成功2",value)
},(reason) => {
console.log("失败2")
})
then方法中,出现错误,将返回的Promise实例改为rejected状态,并把错误信息会被下一个then的形参接收
示例:
// 如果Promise的状态改变,then里的方法不会执行
const p = new Promise((resolve, reject) => {
resolve()
})
const t = p.then.((value) => {
console.log("成功")
// 如果这里代码出错,会将t实例的状态改为rejected
console.log(a)//a不存在
// 使用return可以将t实例的状态改为fulfilled
return 123
},(reason) => {
console.log("失败")
})
t.then.((value) => {
console.log("成功2",value)
},(reason) => {
console.log("失败2")
})
2)catch方法
1. 当Promise的状态改为rejcted.被执行
2. 当Promise执行过程出现代码错误时,被执行
示例:
const p = new Promise((resolve, reject) => {
// reject()
// console.log(a)
throw new Error("出错了");
})
// 思考: catch中的参数函数在什么时候被执行
// 1. 当Promise的状态改为rejcted.被执行
// 2. 当Promise执行过程出现代码错误时,被执行
p.catch((reason => {
console.log("失败", reason)
})
console.log(p);
解决回调地狱
// 封装ajax请求
function getData(url, data = {}){
return new Promise((resolve, reject) => {
$.ajax({
// 发送请求类型
type: "GET",
url: url,
data: data,
success: function (res) {
// 修改Promise状态为成功, 修改Promise的结果res
resolve(res)
},
error:function (res) {
// 修改Promise的状态为失败,修改Promise的结果res
reject(res)
}
})
}
}
// 调用函数
getData("data1.json")
.then((data) => {
// console.log(data)
const { id } = data
return getData("data2.json", {id})
})
.then((data) => {
// console.log(data)
const { usename } = data
return getData("data3.json", {usename})
})
.then((data) => {
console.log(data)
})
promise并发请求
使用Promise.all方法可以完成并发请求,all方法接收一个Promise数组,同样的数据以数组形式传给then的形参
示例:
Promise.all([
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("这是第一个请求")
},1000)
}),
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("这是第二个请求")
},2000)
}),
]).then(res=>{
console.log(res)
})