Promise 是异步编程的一种解决方案,解决了传统异步方案的弊端(回调函数和事件)
异步操作
开始说promise之前,先看一段模拟的网络请求代码
function request(url, successCallback, failCallback) {
// 模拟网络请求
setTimeout(() => {
if (url === "baidu") {
// 成功
let data = ["苹果", "香蕉", "梨子"];
successCallback(data);
} else {
// 失败
let errMsg = "请求失败";
failCallback(errMsg);
}
},1000);
}
// main.js
request(
"baidu",
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
);

调用request这个请求函数,多数情况自然是为了获取请求的数据,所以很容易想到在成功或者失败的时候通过return来返回数据,但是由于网络请求是异步的,request无法获得请求返回的参数。
换个思路,通过回调函数的形式来获取值,如上代码,结果是成功了,但是这种回调的方式有很多弊端,如果是我们自己封装的request,必须要自己设计好callback名称, 并且使用好。
更好的方案:承诺(Promise),规范了代码编写的逻辑,有了承诺,就不用管什么时候返回结果,只要给一个承诺,成功的时候就调用承诺的then()方法,失败的时候就掉用承诺的catch()方法
Promise介绍
上面这个方案就是Promise,Promise是一个类,可以翻译成“承诺”,这是在es6里新增的语法,当需要给调用者一个承诺:“等下我会给你回调函数”时,就可以创建一个Promise对象。在通过new创建Promise对象时,需要传入一个回调函数,称之为executor(执行者)
- 这个回调函数会被立即执行,该函数有两个回调函数resolve,reject
- 调用resolve回调函数时,会执行Promise对象的then方法传入的回调函数
- 调用reject回调函数时,会执行Promise对象的catch方法传入的回调函数
基本使用
成功时,回调resolve函数
失败时,回调reject函数
传入Promise的这个回调函数会立即执行(就是Promise的constructor中调用了这个回调函数,所以会立即执行)
// 返回一个承诺,承诺执行了resolve或者reject回调函数,就执行then或catch方法里的回调
const promise = new Promise((resolve, reject) => {
resolve();
// reject()
});
// then方法传入的回调函数,会在Promise执行resolve函数时被回调
promise.then((res) => {});
// catch方法传入的回调函数,会在Promise执行reject函数时被回调
promise.catch((err) => {});
结合上面网络请求的例子
// request.js
function request(url) {
return new Promise((resolve, reject) => {
// 模拟网络请求
setTimeout(() => {
if (url === "baidu") {
// 成功
let data = ["苹果", "香蕉", "梨子"];
resolve(data);
} else {
// 失败
let errMsg = "请求失败";
reject(errMsg);
}
}, 1000);
});
}
// main.js
// then方法传入的回调函数两个回调函数:
// > 第一个回调函数, 会在Promise执行resolve函数时, 被回调
// > 第二个回调函数, 会在Promise执行reject函数时, 被回调
request("baidu").then(
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
);

Promise的状态
Promise有三种状态,这种状态不受外界影响
- 待定(Pending):初识状态,既没有被兑现,也没有被拒绝,当执行executor中的代码时,处于该状态
- 已兑现(Fulfilled):操作成功完成,执行了resolve时,处于该状态
- 已拒绝(Rejected):操作失败,执行了reject时,处于该状态
一旦状态改变就不会再变 (两种状态改变:成功或失败),比如先执行了resolve,状态就变成了Fulfilled,这时再执行reject也不能将状态改成Rejected了
- Pending -> Fulfilled
- Pending -> Rejected
resolve参数
- 可以传入普通的值或者对象
- 可以传入一个Promise对象
new Promise((resolve, reject) => {
// 正常情况下,状态会从pending -> fulfilled
// 但当传入一个Promise时,状态会由resolove中传入的Promise对象来决定,相当于状态进行了移交
resolve(
new Promise((resolve, reject) => {
// 这里调用resolve,才能让上一层的Promise的状态由pending转为fulfilled
resolve("我是内部的promise");
})
);
}).then(
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
);

- 传入一个对象,并且这个对象有实现then方法
new Promise((resolve, reject) => {
const obj = {
then: function (resolve, reject) {
resolve("obj的then方法的resolve");
// reject()
},
};
// 传入obj时,里面的then方法会被自动执行
resolve(obj);
}).then(
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
);

网友评论