聊聊Promise
前言
面试官:
你在工作中有使用到promise吗?
all,race方法有什么区别知道吗?
怎么捕捉promise错误?
我们来做一道经典的面试题?
这题我记着背过啊,先同步在异步,然后微任务,宏任务。。。。,然后就没有然后了
什么是promise
Promises/A+规范:promisesaplus.com/#notes
具体使用
// 基础使用
// 1.Promise 是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
// 2.Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待pending
// pending->fulfilled
// pending->rejected
// 一旦状态确定就不可更改
// 3. resolve和reject函数是用来更改状态的
// resolve:fulfilled
// reject:rejected
// 4. then方法内部做的事情就判断状态 如果状态是成功 调用成功的回调函数 如果是状态失败 调用失败的回调函数 then方法是定义在原型上的
// 5.then 成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败后的原因
const MyPromise = require("./myPromise");
new Promise((resolve, reject) => {
resolve('成功') //返回成功值
// reject('失败') //返回错误结果
});
实现Promsie
定义基础类
// 定义基础状态
const PENDING = "pending"; //等待
const FULFILLED = "fulfiled"; //成功
const REJECTED = "rejected"; //失败
// 实现基础类
class Mypromise {
constructor(executor) {
// 捕获执行器错误
try {
executor(resolve, reject);
} catch (error) {
this.reject(error)
}
}
//promise状态
status = PENDING;
// 成功之后的值
vlaue = undefined;
// 失败后的原因
reason = undefined;
resolve = (value) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status != PENDING) return;
//将状态更改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
};
reject = (reason) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status != PENDING) return;
//将状态更改为失败
this.status = REJECTED;
//保存失败后的原因
this.reason = reason;
};
then(successCallback, failCallback) {
//判断状态
if (this.status === FULFILLED) {
// 调用成功回调
successCallback(this.value);
} else {
//调用失败回调
failCallback(this.reason);
}
}
}
module.exports = Mypromise;
处理异步逻辑
如果是pending状态下对回调进行缓存
then(successCallback, failCallback) {
//判断状态
if (this.status === FULFILLED) {
// 调用成功回调
successCallback(this.value);
} else if (this.status === REJECTED) {
//调用失败回调
failCallback(this.reason);
} else {
this.successCallback = successCallback;
this.failCallback = failCallback;
}
}
resolve = (value) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status != PENDING) return;
//将状态更改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
//判断成功回调是否存在,如果存在调用
this.successCallback && this.successCallback(this.value);
};
reject = (reason) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status != PENDING) return;
//将状态更改为失败
this.status = REJECTED;
//保存失败后的原因
this.reason = reason;
//判断失败回调是否存在,如果存在 调用
this.failCallback && this.failCallback(this.reason);
};
实现then方法多次调用
将回调修改为数组进行存储
then(successCallback, failCallback) {
//判断状态
if (this.status === FULFILLED) {
// 调用成功回调
successCallback(this.value);
} else if (this.status === REJECTED) {
//调用失败回调
failCallback(this.reason);
} else {
// pending状态下处理逻辑
// 将成功回调和失败回调存储起来
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
}
遍历数组,执行回调
resolve = (value) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status != PENDING) return;
//将状态更改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
//判断成功回调是否存在,如果存在调用
// this.successCallback && this.successCallback(this.value);
while(this.successCallback.length){
this.successCallback.shift()(this.value)
}
};
reject = (reason) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status != PENDING) return;
//将状态更改为失败
this.status = REJECTED;
//保存失败后的原因
this.reason = reason;
//判断失败回调是否存在,如果存在 调用
// this.failCallback && this.failCallback(this.reason);
while(this.failCallback.length){
this.failCallback.shift()(this.reason)
}
};
实现then方法链式调用
then(successCallback, failCallback) {
let promise2 = new Mypromise((resolve, reject) => {
//判断状态
if (this.status === FULFILLED) {
// 调用成功回调
let x = successCallback(this.value);
// 判断x的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(x, resolve, reject);
} else if (this.status === REJECTED) {
//调用失败回调
failCallback(this.reason);
} else {
// pending状态下处理逻辑
// 将成功回调和失败回调存储起来
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
});
return promise2;
}
function resolvePromise(x, resolve, reject) {
if (x instanceof Mypromise) {
x.then(resolve, reject);
} else {
//普通值
resolve(x);
}
}
实现then方法链式调用识别promise对象自调用
then(successCallback, failCallback) {
let promise2 = new Mypromise((resolve, reject) => {
//判断状态
if (this.status === FULFILLED) {
// 变为异步代码
setTimeout(() => {
let x = successCallback(this.value);
// 判断x的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promsie2, x, resolve, reject);
}, 0);
} else if (this.status === REJECTED) {
//调用失败回调
failCallback(this.reason);
} else {
// pending状态下处理逻辑
// 将成功回调和失败回调存储起来
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
});
return promise2;
}
function resolvePromise(promise2, x, resolve, reject) {
//判断是不是返回了自己
if (promise2 === x) {
return reject(new TypeError(""));
}
if (x instanceof Mypromise) {
x.then(resolve, reject);
} else {
//普通值
resolve(x);
}
}
错误捕获
执行器错误捕获
class Mypromise{
constructor(executor) {
// 捕获执行器错误
try {
executor(resolve, reject);
} catch (error) {
this.reject(error);
}
}
}
对回调执行进行错误捕获并返回
then(successCallback, failCallback) {
let promise2 = new Mypromise((resolve, reject) => {
//判断状态
if (this.status === FULFILLED) {
// 变为异步代码
setTimeout(() => {
try {
let x = successCallback(this.value);
// 判断x的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promsie2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.status === REJECTED) {
// 变为异步代码
setTimeout(() => {
try {
let x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promsie2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
// pending状态下处理逻辑
// 将成功回调和失败回调存储起来
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value);
// 判断x的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promsie2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promsie2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise2;
}
将then方法的参数修改为可选参数
then(successCallback, failCallback){
// 给回调新增默认值
successCallback = successCallback ? successCallback :value => value;
failCallback = failCallback ? failCallback : reason => {throw reason};
}
实现promise.all()方法
static all(array){
//结果数组
let result=[]
let index=0
return new Mypromise((resolve,reject)=>{
function addData(key,value){
result[key] =value
index++
if(index===array.length){
resolve(result)
}
}
for(let i=0;i<array.length;i++){
let current = array[i]
if(current instanceof Mypromise){
//promise对象
current.then(value=>addData(i,value),reason=>reject(reason))
}else{
//普通值
addData(i,array[i])
}
}
})
}
promise.resolve()方法实现
static resolve(value) {
if (value instanceof Mypromise) return vlaue;
// 如果传递不是promise类型转为promise再返回
return new Mypromise((resolve) => resolve(value));
}
Promise.prototype.finally()方法实现
finally(callback) {
// 实现异步返回
return this.then(
(value) => {
return Mypromise.resolve(callback()).then(() => value);
},
(reason) => {
callback();
return Mypromise.resolve(callback().then(()=>{throw reason}))
}
);
}
Promise.prototype.catch()方法实现
catch(failCallback){
return this.then(undefined,failCallback)
}
promise.race()方法实现
static race(array){
return new MyPromise((resolve,reject)=>{
for (let i = 0; i < array.length; i++) {
let current = array[i];
current.then(
(value) => resolve(value),
(reason) =>{
reject(reason)
}
);
}
})
}
promise.allSettled()方法实现
static allSettled(array){
const result=[]
let index = 0;
return new MyPromise((resolve,reject)=>{
function addData(key, value,status) {
result[key] = {status:status,value};
index++;
if (index === array.length) {
resolve(result);
}
}
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof MyPromise) {
// promise对象
current.then(
(value) => addData(i, value,'fulfilled'),
(reason) =>addData(i,reason,'rejected')
);
} else {
//普通值
addData(i, array[i]);
}
}
})
}
promise.any()方法实现
static any(array){
let errs=[]
let len =array.length
return new MyPromise((resolve,reject)=>{
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof MyPromise) {
current.then(value=>resolve(value),err=>{
len--
errs.push(err)
if(len===0){
reject(new AggregateError(errs))
}
})
}
}
})
}
最后
如果你能看到这里,并且把所有代码亲自实现过一遍,开头的问题对你来说也就不是问题了,对于那道经典的面试题可能还需要掌握一些知识,也就是js的事件循环,这也是下篇文章要讲的内容了,且听下回分解,如果觉得这篇文章对你有帮助的话,帮忙点一下赞,salut!
转载自:https://juejin.cn/post/7245613765692768313