Promise是一种异步编程的解决方案,用于处理异步操作并返回结果。
主要作用是解决回调函数嵌套(回调地狱)的问题,使异步操作更加清晰、易于理解和维护。
Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。当一个Promise被创建时,它的状态为pending。当异步操作完成并成功时,Promise的状态会变为fulfilled,并返回一个结果。当异步操作失败时,Promise的状态会变为rejected,并返回一个错误信息。
// 创建一个promise
let promise = new Promise(function(resolve, reject) {
// 异步操作
if (异步操作成功) {
resolve(value); // 将异步操作的结果传递给Promise对象,状态变为fulfilled
} else {
reject(error); // 将异步操作的错误信息传递给Promise对象,状态变为rejected
}
});
promise.then(function(result) {
// 异步操作成功时的处理代码
}).catch(function(error) {
// 异步操作失败时的处理代码
});
then
then中一般传入两个参数(函数),第一个对应resolve成功的回调,第二个对应reject失败的回调,如下
function onResolved(res) {
console.log("resolved-" + res); // resolved-成功了
}
function onRejected(err) {
console.log("rejected-" + err); // rejected-失败了
}
new Promise((resolve, reject) => {
resolve('成功了');
// reject('失败了')
}).then(onResolved, onRejected);
then的第二个参数就等同于catch方法,但是需要注意
catch
捕捉promise错误函数,和then的第二个参数(函数)作用一样,处理错误,由于Promise抛出错误具有冒泡性质,能够不断传递,会传到catch中,所以一般来说所有错误处理放在catch中,then中只处理成功的,同时catch还会捕捉then中第一个参数(函数)抛出的异常
new Promise((resolve, reject) => {
reject();
}).catch((err)=> {
console.log(err)
});
finally
finally 方法没有参数,也不会改变 Promise 的状态,它只是在 Promise 结束时提供了一个通知机制,让我们可以在 Promise 结束后执行一些清理工作(比如操作文件的时候关闭文件流)。
function onFinally() {
console.log('结束');
}
new Promise((resolve, reject) => {}).finally(onFinally);
all
接受一个具有Iterable接口的类型,如数组,Map,Set,传入多个promise,
每一个promise执行成功resolve,最后才执行成功(返回一个Promise实例),进入then,否则失败进入catch
function p1() {
var promise1 = new Promise(function (resolve, reject) {
console.log("p1的第一条输出语句");
resolve("p1完成");
});
return promise1;
}
function p2() {
var promise2 = new Promise(function (resolve, reject) {
console.log("p2的第一条输出语句");
setTimeout(() => {
console.log("p2的第二条输出语句");
resolve("p2完成");
}, 2000);
});
return promise2;
}
function p3() {
var promise3 = new Promise(function (resolve, reject) {
console.log("p3的第一条输出语句");
resolve("p3完成");
});
return promise3;
}
Promise.all([p1(), p2(), p3()]).then(function (data) {
console.log(data);
});
// 输出
// p1的第一条输出语句;
// p2的第一条输出语句;
// p3的第一条输出语句;
// p2的第二条输出语句[("p1完成", "p2完成", "p3完成")];
var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
setTimeout(resolve, 4000, 'four');
});
var p5 = new Promise((resolve, reject) => {
reject('reject');
// setTimeout(resolve, 5000, 'five');
});
Promise.all([p1, p2, p3, p4, p5]).then(values => {
console.log(values); // [ 'one', 'two', 'three', 'four', 'five' ]
}, reason => {
console.log(reason) // reject
});
allSettled
接受一个具有Iterable接口的类型,如数组,Map,Set,传入多个promise,
每个promise状态改变成fulfilled或者rejected之后返回,返回的是一个数组对象,对象中有状态status和每一项的返回结果value
Promise.allSettled([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});
// [
// { status: 'fulfilled', value: 'one' },
// { status: 'fulfilled', value: 'two' },
// { status: 'fulfilled', value: 'three' },
// { status: 'fulfilled', value: 'four' },
// { status: 'rejected', reason: 'reject' }
// ]
race
以快为准,数组中所有的promise对象,有一个先执行了何种状态,该对象就为何种状态,并执行相应函数
接受一个具有Iterable接口的类型,如数组,Map,Set,传入多个promise,
其中有一个promise返回了,不管是fulfilled或者rejected,直接返回这个promise的结果
function p1() {
var promise1 = new Promise(function (resolve, reject) {
console.log("p1的第一条输出语句");
resolve("p1完成");
});
return promise1;
}
function p2() {
var promise2 = new Promise(function (resolve, reject) {
console.log("p2的第一条输出语句");
setTimeout(() => {
console.log("p2的第二条输出语句");
resolve("p2完成");
}, 2000);
});
return promise2;
}
function p3() {
var promise3 = new Promise(function (resolve, reject) {
console.log("p3的第一条输出语句");
resolve("p3完成");
});
return promise3;
}
Promise.race([p1(), p2(), p3()]).then(function (data) {
console.log(data);
});
// 输出
// p1的第一条输出语句
// p2的第一条输出语句
// p3的第一条输出语句
// p1完成
any
接受一个具有Iterable接口的类型,如数组,Map,Set,传入多个promise,
当传入的任何一个promise成功的时候,不管其他是否成功或者失败,会把成功的那个promise返回
如果传入的是一个空的数组(Map,Set),返回一个已失败状态的promise,如下
Promise的以上方法都属于 微任务。当Promise状态变为已解决(resolved)或被拒绝(rejected)时,这些方法会产生微任务。这些微任务会在主线程空闲时按照顺序依次执行。
手写实现有助于我们更好的理解Promise,开始吧!
我们使用Es6类的方式,构建一个Promise,更直观好理解
先写出一个雏形,维护三种状态,并定义reslove、reject、和then方法
class MyPromise {
static PENDING = "等待";
static FULFILLED = "成功";
static REJECTED = "失败";
constructor(func) {
this.status = MyPromise.PENDING; // 定义状态
this.result = null; // 定义返回结果
func(this.reslove.bind(this), this.reject.bind(this)); // 执行传入的函数
}
reslove(result) {
this.status = MyPromise.FULFILLED; // 更改状态
this.result = result;
}
reject(result) {
this.status = MyPromise.FULFILLED; // 更改状态
this.result = result;
}
then(onFULFILLED, onREJECTED) {
if (this.status === MyPromise.FULFILLED) {
// 执行成功后的回调
onFULFILLED()
}
if (this.status === MyPromise.REJECTED) {
// 执行失败后的回调
onREJECTED()
}
}
}
注意
当Promise中抛出错误时,会把promise的状态改为失败并且将错误设置为结果,如下
const p = new Promise((resolve,reject)=> {
throw new Error('出错')
})
p.then((res)=> {
console.log(res)
},(err)=> {
console.log(err.message) // log: 出错
})
then中两个参数可以传入undefined
const p = new Promise((resolve,reject)=> {
resolve('成功')
})
p.then(undefined,(err)=> {
console.log(err)
})
完善一下上面的两个问题,代码如下
class MyPromise {
static PENDING = "等待";
static FULFILLED = "成功";
static REJECTED = "失败";
constructor(func) {
this.status = MyPromise.PENDING; // 定义状态
this.result = null; // 定义返回结果
// 当Promise中抛出错误时,会把promise的状态改为失败并且将错误设置为结果
try {
func(this.reslove.bind(this), this.reject.bind(this)); // 执行传入的函数
} catch (err) {
this.reject(err);
}
}
reslove(result) {
this.status = MyPromise.FULFILLED; // 更改状态
this.result = result;
}
reject(result) {
this.status = MyPromise.FULFILLED; // 更改状态
this.result = result;
}
then(onFULFILLED, onREJECTED) {
// then中两个参数可以传入undefined,做下处理
onFULFILLED =
typeof onFULFILLED === "function"
? onFULFILLED
: (value) => {
value;
};
onREJECTED =
typeof onREJECTED === "function"
? onREJECTED
: (reason) => {
throw reason;
};
if (this.status === MyPromise.FULFILLED) {
// 执行成功后的回调
onFULFILLED(this.result);
}
if (this.status === MyPromise.REJECTED) {
// 执行失败后的回调
onREJECTED(this.result);
}
}
}
继续完善
我们先写一个真实promises,看一下下面代码的执行顺序
console.log('第一步')
const p = new Promise((resolve,reject)=> {
console.log('第二步')
setTimeout(() => {
resolve('成功')
console.log('第四步')
});
})
p.then((res)=> {
console.log(res)
},(err)=> {
console.log(err)
})
console.log('第三步')
// 依次输出如下:
// 第一步
// 第二步
// 第三步
// 第四步
// 成功
可以看到,then里面的代码是最后执行的,then属于微任务,resolve和reject 属于在事件循环末尾执行的,因此完善一下实现代码
class MyPromise {
static PENDING = "等待";
static FULFILLED = "成功";
static REJECTED = "失败";
constructor(func) {
this.status = MyPromise.PENDING; // 定义状态
this.result = null; // 定义返回结果
this.resloveCallbacks = []; // 存放reslove回调函数的数组
this.rejectCallbacks = []; // 存放reject回调函数的数组
// 当Promise中抛出错误时,会把promise的状态改为失败并且将错误设置为结果
try {
func(this.reslove.bind(this), this.reject.bind(this)); // 执行传入的函数
} catch (err) {
this.reject(err);
}
}
reslove(result) {
// resolve是在事件循环末尾执行的,所以这里用setTimeout包裹一下
setTimeout(() => {
this.status = MyPromise.FULFILLED; // 更改状态
this.result = result;
// 遍历执行PENDING状态时保存的reslove回调函数
this.resloveCallbacks.forEach((callback) => {
callback(result);
});
});
}
reject(result) {
// reject同样用setTimeout包裹一下
setTimeout(() => {
this.status = MyPromise.FULFILLED; // 更改状态
this.result = result;
// 遍历执行PENDING状态时保存的reject回调函数
this.rejectCallbacks.forEach((callback) => {
callback(result);
});
});
}
then(onFULFILLED, onREJECTED) {
// then中两个参数可以传入undefined,做下处理
onFULFILLED =
typeof onFULFILLED === "function"
? onFULFILLED
: (value) => {
value;
};
onREJECTED =
typeof onREJECTED === "function"
? onREJECTED
: (reason) => {
throw reason;
};
if (this.status === MyPromise.PENDING) {
// PENDING状态时
this.resloveCallbacks.push(onFULFILLED);
this.rejectCallbacks.push(onREJECTED);
}
if (this.status === MyPromise.FULFILLED) {
setTimeout(() => {
// 执行成功后的回调
onFULFILLED(this.result);
})
}
if (this.status === MyPromise.REJECTED) {
setTimeout(() => {
// 执行失败后的回调
onREJECTED(this.result);
})
}
}
}
OK,到此我们可以测试一下
console.log('第一步')
const p = new MyPromise((resolve,reject)=> {
console.log('第二步')
setTimeout(() => {
resolve('成功')
console.log('第四步')
});
})
p.then((res)=> {
console.log(res)
},(err)=> {
console.log(err)
})
console.log('第三步')
// 第一步
// 第二步
// 第三步
// 第四步
// 成功
下面进入重头戏-----then的 链式调用
先看一下示例,如下
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功");
});
});
p.then((res) => {
console.log("第一次then", res);
return '返回一个正常值'
// return new Promise((resolve)=> {
// setTimeout(() => {
// resolve('返回一个promise')
// });
// })
// throw "抛出一个异常"
}).then(
(res) => {
console.log("第二次then", res);
},
(err) => {
console.log("第二次then", err);
}
);
// 第一次then 成功
// 第二次then 返回一个正常值 | 第二次then 返回一个promise |第二次then 抛出一个异常
如果 then 返回的是一个正常值,那么就会把这个结果(value)作为参数,传递给下一个 then 的成功的回调(onFULFILLED);
如果 then 中抛出了异常,那么就会把这个异常(reason)作为参数,传递给下一个 then 的失败的回调(onREJECTED);
如果 then 返回的是一个 promise 或者其他 thenable 对象,那么需要等这个 promise 执行完成,promise 如果成功,就走下一个 then 的成功回调;如果失败,就走下一个 then 的失败回调
要实现上面功(链式调用),我们需要在then方法中,返回一个 promise
then(onFULFILLED, onREJECTED) {
let newPromise = new MyPromise((resolve, reject) => {
// then中两个参数可以传入undefined,做下处理
onFULFILLED =
typeof onFULFILLED === "function"
? onFULFILLED
: (value) => {
value;
};
onREJECTED =
typeof onREJECTED === "function"
? onREJECTED
: (reason) => {
throw reason;
};
if (this.status === MyPromise.PENDING) {
// PENDING状态时
this.resloveCallbacks.push(() => {
try {
let nextResult = onFULFILLED(this.result);
resolve(nextResult)
} catch (err) {
reject(err);
}
});
this.rejectCallbacks.push(() => {
try {
let nextResult = onREJECTED(this.result);
resolve(nextResult)
} catch (err) {
reject(err);
}
});
}
if (this.status === MyPromise.FULFILLED) {
setTimeout(() => {
try {
// 执行成功后的回调
let nextResult = onFULFILLED(this.result);
resolve(nextResult)
} catch (err) {
reject(err);
}
});
}
if (this.status === MyPromise.REJECTED) {
setTimeout(() => {
try {
// 执行失败后的回调
let nextResult = onREJECTED(this.result);
resolve(nextResult)
} catch (err) {
reject(err);
}
});
}
});
return newPromise;
}
这时我们测试一下,已经能实现链式调用了
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("成功");
});
});
p.then((res) => {
console.log("第一次then", res);
return "返回一个正常值";
}).then(
(res) => {
console.log("第二次then", res);
},
(err) => {
console.log("第二次then", err);
}
);
// 第一次then 成功
// 第二次then 返回一个正常值
这样就完成了吗?并没有
上面我们的then执行回调的地方,我们获取到回调执行结果之后就直接resolve出去了,如下
try {
let nextResult = onFULFILLED(this.result);
resolve(nextResult)
} catch (err) {
reject(err);
}
对于我们上面例子,直接返回一个基本数据类型(“返回一个正常值”)是可以实现的,
但是回调执行返回的结果,还可能存在其他类型,比如返回一个函数或者返回一个promise,或者失败抛出一个错误等等,对于这些情况,我们也需要进行处理
完善then的链式调用-----处理then中返回
我们封装一个resolvePromise方法,用来处理不同情况
then(onFULFILLED, onREJECTED) {
let newPromise = new MyPromise((resolve, reject) => {
// then中两个参数可以传入undefined,做下处理
onFULFILLED =
typeof onFULFILLED === "function"
? onFULFILLED
: (value) => {
value;
};
onREJECTED =
typeof onREJECTED === "function"
? onREJECTED
: (reason) => {
throw reason;
};
if (this.status === MyPromise.PENDING) {
// PENDING状态时
this.resloveCallbacks.push(() => {
try {
let nextResult = onFULFILLED(this.result);
resolvePromise(newPromise, nextResult, resolve, reject);
} catch (err) {
reject(err);
}
});
this.rejectCallbacks.push(() => {
try {
let nextResult = onREJECTED(this.result);
resolvePromise(newPromise, nextResult, resolve, reject);
} catch (err) {
reject(err);
}
});
}
if (this.status === MyPromise.FULFILLED) {
setTimeout(() => {
try {
// 执行成功后的回调
let nextResult = onFULFILLED(this.result);
resolvePromise(newPromise, nextResult, resolve, reject);
} catch (err) {
reject(err);
}
});
}
if (this.status === MyPromise.REJECTED) {
setTimeout(() => {
try {
// 执行失败后的回调
let nextResult = onREJECTED(this.result);
resolvePromise(newPromise, nextResult, resolve, reject);
} catch (err) {
reject(err);
}
});
}
});
return newPromise;
}
根据promise规范,实现的resolvePromise
function resolvePromise(newPromise, x, resolve, reject) {
if (x === newPromise) {
// 因为x是回调的结果值,如果x指向newPromise即自己,那么会重新解析自己,导致循环调用
throw new TypeError("禁止循环调用");
}
// 如果x是一个Promise,我们必须等它完成(失败或成功)后得到一个普通值时,才能继续执行。
// 那我们把要执行的任务放在x.then()的成功回调和失败回调里面即可
// 这就表示x完成后就会调用我们的代码。
// 但是对于成功的情况,我们还需要再考虑下,x.then成功回调函数的参数,我们称为y
// 那y也可能是一个thenable对象或者promise
// 所以如果成功时,执行resolvePromise(promise2, y, resolve, reject)
// 并且传入resolve, reject,当解析到普通值时就resolve出去,反之继续解析
// 这样子用于保证最后resolve的结果一定是一个非promise类型的参数
if (x instanceof MyPromise) {
x.then(
(y) => {
resolvePromise(newPromise, y, resolve, reject);
},
(r) => reject(r)
);
}
// (x instanceof myPromise) 处理了promise的情况,但是很多时候交互的promise可能不是原生的
// 就像我们现在写的一个myPromise一样,这种有then方法的对象或函数我们称为thenable。
// 因此我们需要处理thenable。
else if ((typeof x === "object" || typeof x === "function") && x !== null) {
// 暂存x这个对象或函数的then,x也可能没有then,那then就会得到一个undefined
try {
var then = x.then;
} catch (e) {
// 如果读取then的过程中出现异常则reject异常出去
return reject(e);
}
// 判断then是否函数且存在,如果函数且存在那这个就是合理的thenable,我们要尝试去解析
if (typeof then === "function") {
// 状态只能更新一次使用一个called防止反复调用
// 因为成功和失败的回调只能执行其中之一
let called = false;
try {
then.call(
x,
(y) => {
// called就是用于防止成功和失败被同时执行,因为这个是thenable,不是promise
// 需要做限制如果newPromise已经成功或失败了,则不会再处理了
if (called) return;
called = true;
resolvePromise(newPromise, y, resolve, reject);
},
(r) => {
// called就是用于防止成功和失败被同时执行,因为这个是thenable,不是promise
// 需要做限制如果newPromise已经成功或失败了,则不会再处理了
if (called) return;
called = true;
reject(r);
}
);
// 上面那一步等价于,即这里把thenable当作类似于promise的对象去执行then操作
// x.then(
// (y) => {
// if (called) return;
// called = true;
// resolvePromise(newPromise, y, resolve, reject);
// },
// (r) => {
// if (called) return;
// called = true;
// reject(r);
// }
// )
} catch (e) {
// called就是用于防止成功和失败被同时执行,因为这个是thenable,不是promise
// 需要做限制如果newPromise已经成功或失败了,则不会再处理了
if (called) return;
called = true;
reject(e);
}
} else {
// 如果是对象或函数但不是thenable(即没有正确的then属性)
// 当成普通值则直接resolve出去
resolve(x);
}
} else {
return resolve(x);
}
}
测试一下
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("成功");
});
});
p.then((res) => {
console.log("第一次then", res);
// return "返回一个正常值"; // 第二次then 返回一个正常值
// return new MyPromise((resolve) => {
// setTimeout(() => {
// resolve("返回一个promise"); // 第二次then 返回一个promise
// });
// });
throw "抛出一个异常"; // 第二次then 抛出一个异常
}).then(
(res) => {
console.log("第二次then", res);
},
(err) => {
console.log("第二次then", err);
}
);
上面使用的时候介绍过,catch和then的第二个参数作用一样,所以catch的实现可以基于then
catch(onREJECTED) {
return this.then(null, onREJECTED);
}
测试一下,是没有问题的
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("成功了");
// reject('失败了')
});
});
p.then((res) => {
console.log("成功", res)
throw '出错'
}).catch((err) => {
console.log("失败", err);
});
当状态变化(等待变为成功或者失败)时都会进入finally,所以,依然可以借助then实现
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(123);
});
});
p.finally(() => {
console.log('结束'); // 结束
});
该方法接收一个 Promise 数组(具有 Iterator 接口的对象),返回一个新的 Promise,该 Promise 在所有 Promise 都 resolve 后 resolve,如果其中有一个 Promise reject,则该 Promise 直接 reject。
static all(promises) {
return new MyPromise((resolve, reject) => {
// 创建一个空数组results,用于存储每个Promise的 resolve 结果
const results = [];
let count = 0;
const processResult = (index, result) => {
// 结果存入results数组(具有Iterator接口的对象)中,并更新count变量
results[index] = result;
count++;
if (count === promises.length) {
// 如果count等于Promise 数组(具有Iterator接口的对象)的长度,则说明所有Promise都resolve了,此时调用 resolve 方法
resolve(results);
}
};
// 遍历传入的Promise数组(具有 Iterator 接口的对象),对每个Promise调用then方法
for (const [index, promise] of [...promises].entries()) {
MyPromise.resolve(promise).then((result) => {
processResult(index, result);
}, reject);
}
});
}
测试一下,没问题
function p1() {
var promise1 = new MyPromise(function (resolve, reject) {
console.log("p1的第一条输出语句");
resolve("p1完成");
});
return promise1;
}
function p2() {
var promise2 = new MyPromise(function (resolve, reject) {
console.log("p2的第一条输出语句");
setTimeout(() => {
console.log("p2的第二条输出语句");
resolve("p2完成");
}, 2000);
});
return promise2;
}
function p3() {
var promise3 = new MyPromise(function (resolve, reject) {
console.log("p3的第一条输出语句");
resolve("p3完成");
});
return promise3;
}
MyPromise.all([p1(), p2(), p3()]).then(function (data) {
console.log(data);
});
// 输出
// p1的第一条输出语句;
// p2的第一条输出语句;
// p3的第一条输出语句;
// p2的第二条输出语句[("p1完成", "p2完成", "p3完成")];
var p1 = new MyPromise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
var p2 = new MyPromise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
var p3 = new MyPromise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
var p4 = new MyPromise((resolve, reject) => {
setTimeout(resolve, 4000, 'four');
});
var p5 = new MyPromise((resolve, reject) => {
// reject('reject');
setTimeout(resolve, 5000, 'five');
});
MyPromise.all([p1, p2, p3, p4, p5]).then(values => {
console.log(values); // [ 'one', 'two', 'three', 'four', 'five' ]
}, reason => {
console.log(reason) // reject
});
// 5s后输出 [ 'one', 'two', 'three', 'four', 'five' ]
class MyPromise {
static PENDING = "等待";
static FULFILLED = "成功";
static REJECTED = "失败";
constructor(func) {
this.status = MyPromise.PENDING; // 定义状态
this.result = null; // 定义返回结果
this.resloveCallbacks = []; // 存放reslove回调函数的数组
this.rejectCallbacks = []; // 存放reject回调函数的数组
// 当Promise中抛出错误时,会把promise的状态改为失败并且将错误设置为结果
try {
func(this.reslove.bind(this), this.reject.bind(this)); // 执行传入的函数
} catch (err) {
this.reject(err);
}
}
reslove(result) {
// resolve是在事件循环末尾执行的,所以这里用setTimeout包裹一下
setTimeout(() => {
this.status = MyPromise.FULFILLED; // 更改状态
this.result = result;
// 遍历执行PENDING状态时保存的reslove回调函数
this.resloveCallbacks.forEach((callback) => {
callback(result);
});
});
}
reject(result) {
// reject同样用setTimeout包裹一下
setTimeout(() => {
this.status = MyPromise.FULFILLED; // 更改状态
this.result = result;
// 遍历执行PENDING状态时保存的reject回调函数
this.rejectCallbacks.forEach((callback) => {
callback(result);
});
});
}
then(onFULFILLED, onREJECTED) {
let newPromise = new MyPromise((resolve, reject) => {
// then中两个参数可以传入undefined,做下处理
onFULFILLED =
typeof onFULFILLED === "function"
? onFULFILLED
: (value) => {
value;
};
onREJECTED =
typeof onREJECTED === "function"
? onREJECTED
: (reason) => {
throw reason;
};
if (this.status === MyPromise.PENDING) {
// PENDING状态时
this.resloveCallbacks.push(() => {
try {
let nextResult = onFULFILLED(this.result);
resolvePromise(newPromise, nextResult, resolve, reject);
} catch (err) {
reject(err);
}
});
this.rejectCallbacks.push(() => {
try {
let nextResult = onREJECTED(this.result);
resolvePromise(newPromise, nextResult, resolve, reject);
} catch (err) {
reject(err);
}
});
}
if (this.status === MyPromise.FULFILLED) {
setTimeout(() => {
try {
// 执行成功后的回调
let nextResult = onFULFILLED(this.result);
resolvePromise(newPromise, nextResult, resolve, reject);
} catch (err) {
reject(err);
}
});
}
if (this.status === MyPromise.REJECTED) {
setTimeout(() => {
try {
// 执行失败后的回调
let nextResult = onREJECTED(this.result);
resolvePromise(newPromise, nextResult, resolve, reject);
} catch (err) {
reject(err);
}
});
}
});
return newPromise;
}
catch(onREJECTED) {
return this.then(null, onREJECTED);
}
finally() {
return this.then(undefined, undefined);
}
static resolve(value) {
return new MyPromise((resolve) => {
resolve(value);
});
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
static all(promises) {
return new MyPromise((resolve, reject) => {
// 创建一个空数组results,用于存储每个Promise的 resolve 结果
const results = [];
let count = 0;
const processResult = (index, result) => {
// 结果存入results数组(具有Iterator接口的对象)中,并更新count变量
results[index] = result;
count++;
if (count === promises.length) {
// 如果count等于Promise 数组(具有Iterator接口的对象)的长度,则说明所有Promise都resolve了,此时调用 resolve 方法
resolve(results);
}
};
// 遍历传入的Promise数组(具有 Iterator 接口的对象),对每个Promise调用then方法
for (const [index, promise] of [...promises].entries()) {
Promise.resolve(promise).then((result) => {
processResult(index, result);
}, reject);
}
});
}
}
function resolvePromise(newPromise, x, resolve, reject) {
if (x === newPromise) {
// 因为x是回调的结果值,如果x指向newPromise即自己,那么会重新解析自己,导致循环调用
throw new TypeError("禁止循环调用");
}
// 如果x是一个Promise,我们必须等它完成(失败或成功)后得到一个普通值时,才能继续执行。
// 那我们把要执行的任务放在x.then()的成功回调和失败回调里面即可
// 这就表示x完成后就会调用我们的代码。
// 但是对于成功的情况,我们还需要再考虑下,x.then成功回调函数的参数,我们称为y
// 那y也可能是一个thenable对象或者promise
// 所以如果成功时,执行resolvePromise(promise2, y, resolve, reject)
// 并且传入resolve, reject,当解析到普通值时就resolve出去,反之继续解析
// 这样子用于保证最后resolve的结果一定是一个非promise类型的参数
if (x instanceof MyPromise) {
x.then(
(y) => {
resolvePromise(newPromise, y, resolve, reject);
},
(r) => reject(r)
);
}
// (x instanceof myPromise) 处理了promise的情况,但是很多时候交互的promise可能不是原生的
// 就像我们现在写的一个myPromise一样,这种有then方法的对象或函数我们称为thenable。
// 因此我们需要处理thenable。
else if ((typeof x === "object" || typeof x === "function") && x !== null) {
// 暂存x这个对象或函数的then,x也可能没有then,那then就会得到一个undefined
try {
var then = x.then;
} catch (e) {
// 如果读取then的过程中出现异常则reject异常出去
return reject(e);
}
// 判断then是否函数且存在,如果函数且存在那这个就是合理的thenable,我们要尝试去解析
if (typeof then === "function") {
// 状态只能更新一次使用一个called防止反复调用
// 因为成功和失败的回调只能执行其中之一
let called = false;
try {
then.call(
x,
(y) => {
// called就是用于防止成功和失败被同时执行,因为这个是thenable,不是promise
// 需要做限制如果newPromise已经成功或失败了,则不会再处理了
if (called) return;
called = true;
resolvePromise(newPromise, y, resolve, reject);
},
(r) => {
// called就是用于防止成功和失败被同时执行,因为这个是thenable,不是promise
// 需要做限制如果newPromise已经成功或失败了,则不会再处理了
if (called) return;
called = true;
reject(r);
}
);
// 上面那一步等价于,即这里把thenable当作类似于promise的对象去执行then操作
// x.then(
// (y) => {
// if (called) return;
// called = true;
// resolvePromise(newPromise, y, resolve, reject);
// },
// (r) => {
// if (called) return;
// called = true;
// reject(r);
// }
// )
} catch (e) {
// called就是用于防止成功和失败被同时执行,因为这个是thenable,不是promise
// 需要做限制如果newPromise已经成功或失败了,则不会再处理了
if (called) return;
called = true;
reject(e);
}
} else {
// 如果是对象或函数但不是thenable(即没有正确的then属性)
// 当成普通值则直接resolve出去
resolve(x);
}
} else {
return resolve(x);
}
}