一、Promise是什么?
Promise 是异步编程的一种解决方案,Promise 它为以下三种状态之一:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。一旦Promise 被 resolve 或 reject,不能再迁移至其他任何状态(即状态 immutable)。
1.Promise的基本结构
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("FULFILLED")
})
})
Promise构造函数必须接受一个参数,并且参数是一个函数,我们命名为handle,handle函数又包含两个参数resolve和reject,它们两个是函数。 第一步,我们先定义名为
KPromise的class,它接受一个handle函数作为参数
class KPromise {
constructor (handle) {
}
}
接下来,我们再看promise状态值的处理
2.Promise状态和值
Promise 对象存在以下三种状态:
Pending(进行中)Fulfilled(已成功)Rejected(已失败)
状态只能由
Pending变为Fulfilled或由Pending变为Rejected,且状态改变之后不会在发生变化,会一直保持这个状态。Promise的值是指状态改变时传递给回调函数的值。
上文中
handle函数包含resolve和reject两个参数,它们是两个函数,可以用于改变Promise的状态和传入Promise的值
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("FULFILLED")
})
})
这里 resolve 传入的 "FULFILLED" 就是 Promise 的值
resolve 和 reject
resolve: 将Promise对象的状态从Pending(进行中)变为Fulfilled(已成功)reject: 将Promise对象的状态从Pending(进行中)变为Rejected(已失败)resolve和reject都可以传入任意类型的值作为实参,表示Promise对象成功(Fulfilled)和失败(Rejected)`的值
了解了Promise的状态和值,接下来我们为KPromise添加状态属性和值,并添加改变状态的执行逻辑
class KPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
this['[[PromiseState]]'] = "pending"
this['[[PromiseResult]]'] = "undefined"
// 执行handle
try {
handle(this.#resolve.bind(this), this.#reject.bind(this))
} catch (err) {
this._reject(err)
}
}
#resolve(val) {
this['[[PromiseState]]'] = "fulfilled"
this['[[PromiseResult]]'] = val
}
#reject(err) {
this['[[PromiseState]]'] = "rejected"
this['[[PromiseResult]]'] = err
}
}
这样就实现了 Promise 状态和值的改变。下面说一说 Promise 的核心: then 方法
3.Promise的then方法
Promise 对象的 then 方法接受两个参数,并且为函数。
then参数的调用
- 当
promise状态变为成功时必须被调用,其第一个参数为promise成功状态传入的值(resolve执行时传入的值) - 当
promise状态变为失败时必须被调用,其第一个参数为promise失败状态传入的值(reject执行时传入的值)
let promise = new KPromise((resolve, reject) => {
setTimeout(() => {
resolve("FULFILLED")
}, 1000)
})
// 第一种:then参数的调用
promise.then(res => {
console.log(res); //FULFILLED
}, err => {
})
实现方式:
class KPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
this['[[PromiseState]]'] = "pending"
this['[[PromiseResult]]'] = "undefined"
// 解决了异步处理的问题
// this.resolveFn = undefined;
// this.rejectFn = undefined;
// 执行handle
try {
handle(this.#resolve.bind(this), this.#reject.bind(this))
} catch (err) {
this._reject(err)
}
}
#resolve(val) {
this['[[PromiseState]]'] = "fulfilled"
this['[[PromiseResult]]'] = val
// 解决了异步处理的问题
// this.resolveFn(val);
}
#reject(err) {
this['[[PromiseState]]'] = "rejected"
this['[[PromiseResult]]'] = err
// this.rejectFn(val);
/ run();
// setTimeout(run)
// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("a", "b");
}
then(onResolved, onRejected) {
// 存在异步问题
/**
if(this['[[PromiseState]]'] = "fulfilled") {
onResolved(this['[[PromiseResult]]'])
}else {
onRejected(this['[[PromiseResult]]'])
}*/
//解决了异步处理的问题
/**
this.resolveFn = onResolved;
this.rejectFn = onRejected;
*/
}
}
then多次调用
Promise 对象的 then 方法允许多次调用。
// 第二种:then多次调用,多个then的问题 数组存储 依次执行。
promise.then(res=>{
console.log("1111",res); //1111 FULFILLED
})
promise.then(res=>{
console.log("2222",res); //2222 FULFILLED
})
多个then的实现方式
class KPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
this['[[PromiseState]]'] = "pending"
this['[[PromiseResult]]'] = "undefined"
/ 解决了异步处理的问题
// this.resolveFn = undefined;
// this.rejectFn = undefined;
// 执行handle
try {
handle(this.#resolve.bind(this), this.#reject.bind(this))
} catch (err) {
this._reject(err)
}
}
#resolve(val) {
this['[[PromiseState]]'] = "fulfilled"
this['[[PromiseResult]]'] = val
// 解决了异步处理的问题
// this.resolveFn(val);
// 解决多个then的问题
let run = () => {
let cb;
while (cb = this.resolveQueue.shift()) {
cb && cb(val);
}
}
//会存在着同步的问题
// run();
//解决同步的问题,让执行放在异步队列中,存在宏任务问题
// setTimeout(run)
}
#reject(err) {
this['[[PromiseState]]'] = "rejected"
this['[[PromiseResult]]'] = err
// this.rejectFn(val);
let run = () => {
let cb;
// [fn1,fn2....]
while (cb = this.rejectQueue.shift()) {
cb && cb(err);
}
}
// run();
// setTimeout(run);
}
then(onResolved, onRejected) {
// 存在异步问题
/**
if(this['[[PromiseState]]'] = "fulfilled") {
onResolved(this['[[PromiseResult]]'])
}else {
onRejected(this['[[PromiseResult]]'])
}*/
//解决了异步处理的问题
/**
this.resolveFn = onResolved;
this.rejectFn = onRejected;
*/
//解决多个then的问题
/**
this.resolveQueue.push(onResolved);
this.rejectQueue.push(onRejected);
*/
}
}
promise微任务问题
但以上的写法存在一定的问题,也就是promise(then)是个微任务
// 第三种:(执行顺序问题)微任务宏任务问题,同步-异步-微任务-宏任务
// 222->333->555->111-->444
setTimeout(() => {
console.log(111);
});
console.log(222);
let p = new KPromise((resolve, reject) => {
console.log(333);
resolve("success");
// reject("err")
})
// 先调用resolve 在调用then
p.then(res => {
console.log(444,res);
},err=>{
console.log(err);
})
console.log(555);
KPromise改成微任务的实现方式
class KPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
this['[[PromiseState]]'] = "pending"
this['[[PromiseResult]]'] = "undefined"
/ 解决了异步处理的问题
// this.resolveFn = undefined;
// this.rejectFn = undefined;
// 执行handle
try {
handle(this.#resolve.bind(this), this.#reject.bind(this))
} catch (err) {
this._reject(err)
}
}
#resolve(val) {
this['[[PromiseState]]'] = "fulfilled"
this['[[PromiseResult]]'] = val
// 解决了异步处理的问题
// this.resolveFn(val);
// 解决多个then的问题
let run = () => {
let cb;
while (cb = this.resolveQueue.shift()) {
cb && cb(val);
}
}
//会存在着同步的问题
// run();
//解决同步的问题,让执行放在异步队列中,存在宏任务问题
// setTimeout(run)
// 解决宏任务问题
// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("a", "b")
}
#reject(err) {
this['[[PromiseState]]'] = "rejected"
this['[[PromiseResult]]'] = err
// this.rejectFn(val);
let run = () => {
let cb;
// [fn1,fn2....]
while (cb = this.rejectQueue.shift()) {
cb && cb(err);
}
}
// run();
// setTimeout(run);
// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("a", "b");
}
then(onResolved, onRejected) {
// 存在异步问题
/**
if(this['[[PromiseState]]'] = "fulfilled") {
onResolved(this['[[PromiseResult]]'])
}else {
onRejected(this['[[PromiseResult]]'])
}*/
//解决了异步处理的问题
/**
this.resolveFn = onResolved;
this.rejectFn = onRejected;
*/
//解决多个then的问题
/**
this.resolveQueue.push(onResolved);
this.rejectQueue.push(onRejected);
*/
}
}
then的链式调用
then 方法要链式调用那么就需要返回一个 Promise 对象,then 方法里面 return 一个返回值作为下一个 then 方法的参数,如果是 return 一个 Promise 对象,那么就需要判断它的状态
let p = new KPromise(resolve => {
resolve("success");
})
p.then(res => {
console.log(res);
//return "value";
return new KPromise(resolve=>{
resolve("返还的值");
})
}).then(res => {
console.log(2, res); //2 返还的值
})
链式调用具体的实现方式
class KPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
this['[[PromiseState]]'] = "pending"
this['[[PromiseResult]]'] = "undefined"
/ 解决了异步处理的问题
// this.resolveFn = undefined;
// this.rejectFn = undefined;
// 执行handle
try {
handle(this.#resolve.bind(this), this.#reject.bind(this))
} catch (err) {
this._reject(err)
}
}
#resolve(val) {
this['[[PromiseState]]'] = "fulfilled"
this['[[PromiseResult]]'] = val
// 解决了异步处理的问题
// this.resolveFn(val);
// 解决多个then的问题
let run = () => {
let cb;
while (cb = this.resolveQueue.shift()) {
cb && cb(val);
}
}
//会存在着同步的问题
// run();
//解决同步的问题,让执行放在异步队列中,存在宏任务问题
// setTimeout(run)
// 解决宏任务问题
// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("a", "b")
}
#reject(err) {
this['[[PromiseState]]'] = "rejected"
this['[[PromiseResult]]'] = err
// this.rejectFn(val);
/ run();
// setTimeout(run)
// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("a", "b");
}
then(onResolved, onRejected) {
// 存在异步问题
/**
if(this['[[PromiseState]]'] = "fulfilled") {
onResolved(this['[[PromiseResult]]'])
}else {
onRejected(this['[[PromiseResult]]'])
}*/
//解决了异步处理的问题
/**
this.resolveFn = onResolved;
this.rejectFn = onRejected;
*/
//解决多个then的问题
/**
this.resolveQueue.push(onResolved);
this.rejectQueue.push(onRejected);
*/
//链式调用
return new KPromise((resolve, reject) => {
// let val = onResolved && onResolved();
let resolveFn = function (val) {
let reslut = onResolved && onResolved(val);
// 返还的KPromise对象
if (reslut instanceof KPromise) {
// reslut.then(res=>{
// resolve(res);
// })
reslut.then(resolve);
} else {
resolve(reslut);
}
}
}
this.resolveQueue.push(resolveFn);
let rejectFn = function (err) {
onRejected && onRejected(err);
reject(err);
}
this.rejectQueue.push(rejectFn);
})
}
}
promise的catch
let p = new Promise((resolve, reject) => {
reject("err");
})
p.then(res => {
console.log(res);
}).catch(err => {
console.log(err); //err
})
实现方式
catch(fn) {
return this.then(undefined, fn);
}
promise的resolve和reject
Promise.resolve(2222).then(res => {
console.log(res); //2222
})
Promise.reject(new Error('fail')).then(res => {
},err => {
console.log(err)
})
实现方式
static resolve(val) {
return new KPromise(resolve => {
resolve(val);
})
}
static reject(err) {
return new KPromise((resolve, reject) => {
reject(err);
})
}
promise的race方法
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success1");
reject("err1");
}, 2000);
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success2");
//reject("err2");
}, 1000);
})
KPromise.race([p1,p2]).then(res=>{
console.log(res); //success2
},err=>{
console.log(err);
});
实现方式:
static race(lists) {
let isExe = false;
return new KPromise((resolve, reject) => {
lists.forEach(item => {
item.then(res => {
if (!isExe) {
resolve(res);
isExe = true;
}
}, err => {
if (!isExe) {
reject(err);
isExe = true;
}
})
})
})
}
promise的allSettled
static allSettled(lists) {
// let resArr = [1,2];
let resArr = new Array(lists.length);
let num = 0;
return new KPromise(reslove => {
lists.forEach((item, key) => {
let obj = {};
item.then(res => {
obj['status'] = "fulfilled";
obj['value'] = res;
resArr[key] = obj;
// console.log(1,resArr);
num++;
if (num >= lists.length) {
reslove(resArr);
}
}, err => {
obj['status'] = "rejected";
obj['reson'] = err;
resArr[key] = obj;
num++;
// console.log(2,resArr);
if (num >= lists.length) {
reslove(resArr);
}
})
})
})
}
promise的all
static all(lists){
let resArr = [];
let num = 0;
return new KPromise(resolve=>{
lists.forEach(item=>{
item.then(res=>{
num++;
resArr.push(res);
if(resArr.length===lists.length){
resolve(resArr);
}
})
})
})
}