什么是Promise
Promise 对象用于表示一个异步操作的最终完成(或失败)及其结果值。
Promise的三个状态。
- 待定(pending) :初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled) :意味着操作成功完成。
- 已拒绝(rejected) :意味着操作失败。
Promise状态之间的流转
1.Promise 对象初始化状态为 pending
2.当调用resolve(成功),会由pending => fulfilled
3.当调用reject(失败),会由pending => rejected
Promise比然存在某一种状态,由初始态pending到fulfilled或rejected状态,并且不可更改。
Promise的使用
// 创建了一个promise对象
var promise = new Promise((resolve,reject) => {
// 执行相应的异步逻辑。
})
// 回调完成调用then方法
promise.then((result)=> {
console.log(result);
}, reason => {
console.log(reason) // rejected
})
// reject之后
promise.catch(err=>{
console.error(err);
});
// Promise.all
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// expected output: Array [3, 42, "foo"]
// Promise.race
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
// Both resolve, but promise2 is faster
});
// expected output: "two"
// Promise.allSettled
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];
Promise.allSettled(promises).
then((results) => results.forEach((result) => console.log(result.status)));
// expected output:
// "fulfilled"
// "rejected"
Promise解决了什么问题
回调地狱
Promise解决了js异步编程中回调地狱的问题,可以形象的看下面这张图
在Javascript的早期,实现异步编程的主要模式是回调函数。
function f1(callback){
setTimeout(function () {
// f1的任务代码
callback();
}, 1000);
}
回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。
代码可读性的问题
有编写大量回调函数组成的代码,可读性不高。而Promise的出现,以一种规范化的方式提供异步编程的范式,可读性提高。
信任问题
在传统的回调式异步编程中,回调函数控制成功或失败后的逻辑。
在Promise的方式中,回调只负责成功之后的通知,而回调成功之后的操作放在了then的回调里面,由Promise精确控制。
手写一个Promise
第一步,我们先创建一个Promise类
// 定义三种状态
const PENDING = "pending";
const REJECTED = "rejected";
const FULFILLED = "fulfilled";
class MPromise {
status;
resolveCallbacks = [];
rejectCallbacks = [];
constructor(func) {
this.status = PENDING;
try {
func(this.resolve.bind(this), this.reject.bind(this));
} catch (e) {
// 兼容throw 报错情况。
this.reject(e.message);
}
}
resolve(result) {
setTimeout(() => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.result = result;
this.resolveCallbacks.forEach((cb) => cb(result));
}
});
}
reject(result) {
setTimeout(() => {
if (this.status === PENDING) {
this.status = REJECTED;
this.result = result;
this.rejectCallbacks.forEach((cb) => cb(result));
}
});
}
then(onResolve, onReject) {
return new MPromise((resolve) => {
if (this.status === PENDING) {
this.resolveCallbacks.push(onResolve);
this.rejectCallbacks.push(onReject);
}
if (this.status === FULFILLED) {
setTimeout(() => {
const res = onResolve(this.result);
});
}
if (this.status === REJECTED) {
setTimeout(() => {
onReject(this.result);
});
}
})
}
}
console.log("第一步");
var promise2 = new MPromise((resolve) => {
console.log("第二步");
setTimeout(() => {
console.log("第四步");
resolve(0);
console.log("第五步");
}, 3000);
});
console.log("第三步");
console.log(promise2);
promise2.then((res) => {
console.log(res);
console.log("第六步");
});