1.搭建架子
(function (window) {
// 定义常量
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
// 定义this,防止this指向发生错误
const _this = this;
function resolve(value) {}
function reject(reason) {}
executor(resolve, reject);
}
// 返回一个promise
then() {}
// 返回一个promise
catch() {}
static resolve() {}
static reject() {}
static all() {}
static race() {}
}
console.dir(MyPromise);
window.MyPromise = MyPromise;
})(window);
2.resolve和reject处理状态
- 我们都知道,Promise有三种状态
- pending
- fulfilled
- rejected
- 且状态只能改变一次,且不可逆,即我们即使在Promise内部多次调用resolve/reject,只会触发第一次
- pending -> fulfilled
- 当我们执行resolve时触发
- pending -> rejected
- 当我们执行reject时触发
- pending -> fulfilled
- 由此可以得出,Promise内部执行这两个方法的时候,会改变Promise的状态,且将我们调用的参数传递进去保存
(function (window) {
// 定义常量
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
// 定义this,防止this指向发生错误
const _this = this;
// 初始化参数
_this.PromiseState = PENDING;
_this.PromiseResult = null;
// 主要用于更改Promise的状态和结果
function resolve(value) {
// 当状态不是pending时,不处理
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = FULFILLED;
_this.PromiseResult = value;
}
function reject(reason) {
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = REJECTED;
_this.PromiseResult = reason;
}
executor(resolve, reject);
}
// 返回一个promise
then() {}
// 返回一个promise
catch() {}
static resolve() {}
static reject() {}
static all() {}
static race() {}
}
console.dir(MyPromise);
window.MyPromise = MyPromise;
})(window);
3.then的调用
- 我们都知道,当调用then的时候,会根据当前Promise的状态,来执行then的第一个回调还是第二个回调
- 第一个回调:PromiseState == 'fulfilled'时调用
- 第二个回调:PromiseState == 'rejected'时调用
(function (window) {
// 定义常量
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
// 定义this,防止this指向发生错误
const _this = this;
// 初始化参数
_this.PromiseState = PENDING;
_this.PromiseResult = null;
// 模拟微队列,用于存放回调
_this.callbacks = [];
// 主要用于更改Promise的状态和结果
function resolve(value) {
// 当状态不是pending时,不处理
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = FULFILLED;
_this.PromiseResult = value;
}
function reject(reason) {
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = REJECTED;
_this.PromiseResult = reason;
}
executor(resolve, reject);
}
// 返回一个promise
then(onResolve, onReject) {
// 因为then是同步任务,当Promise内部为异步任务时,会导致then获取不到当前的状态和值,
// 所以当状态为pending时,我们应该将回调存进队列内,当Promise内部执行完毕后,触发回调
if (this.PromiseState === PENDING) {
this.callbacks.push({
onResolve,
onReject,
});
}
}
window.MyPromise = MyPromise;
})(window);
当Promise内部执行完毕后,会根据执行的结果,触发then的回调
(function (window) {
// 定义常量
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
// 定义this,防止this指向发生错误
const _this = this;
// 初始化参数
_this.PromiseState = PENDING;
_this.PromiseResult = null;
// 模拟微队列,用于存放回调
_this.callbacks = [];
// 主要用于更改Promise的状态和结果
function resolve(value) {
// 当状态不是pending时,不处理
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = FULFILLED;
_this.PromiseResult = value;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onResolve(_this.PromiseResult);
});
});
}
}
function reject(reason) {
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = REJECTED;
_this.PromiseResult = reason;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onReject(_this.PromiseResult);
});
});
}
}
executor(resolve, reject);
}
// 返回一个promise
then(onResolve, onReject) {
// 因为then是同步任务,当Promise内部为异步任务时,会导致then获取不到当前的状态和值,
// 所以当状态为pending时,我们应该将回调存进队列内,当Promise内部执行完毕后,触发回调
if (this.PromiseState === PENDING) {
this.callbacks.push({
onResolve,
onReject,
});
}
}
}
console.dir(MyPromise);
window.MyPromise = MyPromise;
})(window);
4.实现then的链式调用
(function (window) {
// 定义常量
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
// 定义this,防止this指向发生错误
const _this = this;
// 初始化参数
_this.PromiseState = PENDING;
_this.PromiseResult = null;
// 模拟微队列,用于存放回调
_this.callbacks = [];
// 主要用于更改Promise的状态和结果
function resolve(value) {
// 当状态不是pending时,不处理
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = FULFILLED;
_this.PromiseResult = value;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onResolve(_this.PromiseResult);
});
});
}
}
function reject(reason) {
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = REJECTED;
_this.PromiseResult = reason;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onReject(_this.PromiseResult);
});
});
}
}
executor(resolve, reject);
}
// 返回一个promise
then(onResolve, onReject) {
const _this = this;
return new MyPromise((resolve, reject) => {
// 因为then是同步任务,当Promise内部为异步任务时,会导致then获取不到当前的状态和值,
// 所以当状态为pending时,我们应该将回调存进队列内,当Promise内部执行完毕后,触发回调
if (_this.PromiseState === PENDING) {
this.callbacks.push({
onResolve,
onReject,
});
} else if (_this.PromiseState === FULFILLED) {
// 当状态为成功时,调用then方法
const result = onResolve(_this.PromiseResult);
// 此时存在两种情况,
// 1.result为非Promise,则result为Promise的值
// 2.result为Promise
// 2.1根据Promise的结果,来决定当前Promise的最新状态和值
if (result instanceof MyPromise) {
// result.then(
// (value) => {
// resolve(value);
// },
// (reason) => {
// reject(reason);
// }
// );
// 简写
result.then(resolve, reject);
} else {
resolve(result);
}
} else {
}
});
}
// 返回一个promise
catch() {}
static resolve() {}
static reject() {}
static all() {}
static race() {}
}
console.dir(MyPromise);
window.MyPromise = MyPromise;
})(window);
同理,当PromiseState == rejected的时候,逻辑和fulfilled是一样的,所以我们可以抽离进行封装, 且then内部为微任务,这里用定时器模拟
(function (window) {
// 定义常量
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
// 定义this,防止this指向发生错误
const _this = this;
// 初始化参数
_this.PromiseState = PENDING;
_this.PromiseResult = null;
// 模拟微队列,用于存放回调
_this.callbacks = [];
// 主要用于更改Promise的状态和结果
function resolve(value) {
// 当状态不是pending时,不处理
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = FULFILLED;
_this.PromiseResult = value;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onResolve(_this.PromiseResult);
});
});
}
}
function reject(reason) {
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = REJECTED;
_this.PromiseResult = reason;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onReject(_this.PromiseResult);
});
});
}
}
// 我们都知道,Promise内部如果抛出异常,则相当于调用了reject
// 这里用trycatch进行捕获
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 返回一个promise
then(onResolve, onReject) {
return new MyPromise((resolve, reject) => {
function handler(callback) {
// 我们都知道,Promise内部如果抛出异常,则相当于调用了reject
// 这里用trycatch进行捕获
try {
// 当状态为成功时,调用then方法
const result = callback(_this.PromiseResult);
// 此时存在两种情况,
// 1.result为非Promise,则result为Promise的值
// 2.result为Promise
// 2.1根据Promise的结果,来决定当前Promise的最新状态和值
if (result instanceof MyPromise) {
// 简写
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 因为then是同步任务,当Promise内部为异步任务时,会导致then获取不到当前的状态和值,
// 所以当状态为pending时,我们应该将回调存进队列内,当Promise内部执行完毕后,触发回调
if (_this.PromiseState === PENDING) {
this.callbacks.push({
onResolve,
onReject,
});
} else if (_this.PromiseState === FULFILLED) {
// 因为 then内部为微任务,所以用定时器模拟
setTimeout(() => {
handler(onResolve);
});
} else {
setTimeout(() => {
handler(onReject);
});
}
});
}
}
console.dir(MyPromise);
window.MyPromise = MyPromise;
})(window);
此时,我们已经处理好then成功和失败的回调,但当状态为pending时,我们调用then方法的回调,并没有对状态进行变更,所以我们需要对该状态进行修改
(function (window) {
// 定义常量
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
// 定义this,防止this指向发生错误
const _this = this;
// 初始化参数
_this.PromiseState = PENDING;
_this.PromiseResult = null;
// 模拟微队列,用于存放回调
_this.callbacks = [];
// 主要用于更改Promise的状态和结果
function resolve(value) {
// 当状态不是pending时,不处理
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = FULFILLED;
_this.PromiseResult = value;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onResolve(_this.PromiseResult);
});
});
}
}
function reject(reason) {
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = REJECTED;
_this.PromiseResult = reason;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onReject(_this.PromiseResult);
});
});
}
}
// 我们都知道,Promise内部如果抛出异常,则相当于调用了reject
// 这里用trycatch进行捕获
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 返回一个promise
then(onResolve, onReject) {
const _this = this;
return new MyPromise((resolve, reject) => {
function handler(callback) {
// 我们都知道,Promise内部如果抛出异常,则相当于调用了reject
// 这里用trycatch进行捕获
try {
// 当状态为成功时,调用then方法
const result = callback(_this.PromiseResult);
// 此时存在两种情况,
// 1.result为非Promise,则result为Promise的值
// 2.result为Promise
// 2.1根据Promise的结果,来决定当前Promise的最新状态和值
if (result instanceof MyPromise) {
// 简写
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 因为then是同步任务,当Promise内部为异步任务时,会导致then获取不到当前的状态和值,
// 所以当状态为pending时,我们应该将回调存进队列内,当Promise内部执行完毕后,触发回调
if (_this.PromiseState === PENDING) {
// pending状态和fulfilled状态一样,也需要判断结果是否为Promise
this.callbacks.push({
onResolve() {
handler(onResolve);
},
onReject() {
handler(onReject);
},
});
} else if (_this.PromiseState === FULFILLED) {
// 因为 then内部为微任务,所以用定时器模拟
setTimeout(() => {
handler(onResolve);
});
} else {
setTimeout(() => {
handler(onReject);
});
}
});
}
}
console.dir(MyPromise);
window.MyPromise = MyPromise;
})(window);
5.catch的完善
当我们完成then之后,catch其实原理和then一样,所以我们可以利用then来实现
// 返回一个promise
catch(onReject) {
return this.then(undefined, onReject);
}
6.Promise对象的resolve和reject的实现
// 调用resolve时,会返回一个Promise对象
// 2.1 当resolve的参数为promise时
// 2.2 当resolve的参数不为promise时,其结果就是promise的结果
static resolve(value) {
return new MyPromise((resolve, reject) => {
if (value instanceof MyPromise) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
// 调用reject时,会返回一个Promise对象
// 与resolve不同的是,reject传入的参数是什么,Promise的结果就是什么
static reject(reason) {
return new MyPromise((resovle, reject) => {
reject(reason);
});
}
7.优化then
// 返回一个promise
then(onResolve, onReject) {
const _this = this;
// 优化,当onResolve,onReject不是函数的时候
// 实现catch和then的参数穿透
onResolve =
typeof onResolve === "function" ? onResolve : (value) => value;
onReject =
typeof onReject === "function"
? onReject
: (reason) => {
throw reason;
};
return new MyPromise((resolve, reject) => {
function handler(callback) {
// 我们都知道,Promise内部如果抛出异常,则相当于调用了reject
// 这里用trycatch进行捕获
try {
// 当状态为成功时,调用then方法
const result = callback(_this.PromiseResult);
// 此时存在两种情况,
// 1.result为非Promise,则result为Promise的值
// 2.result为Promise
// 2.1根据Promise的结果,来决定当前Promise的最新状态和值
if (result instanceof MyPromise) {
// 简写
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 因为then是同步任务,当Promise内部为异步任务时,会导致then获取不到当前的状态和值,
// 所以当状态为pending时,我们应该将回调存进队列内,当Promise内部执行完毕后,触发回调
if (_this.PromiseState === PENDING) {
// pending状态和fulfilled状态一样,也需要判断结果是否为Promise
_this.callbacks.push({
onResolve() {
handler(onResolve);
},
onReject() {
handler(onReject);
},
});
} else if (_this.PromiseState === FULFILLED) {
// 因为 then内部为微任务,所以用定时器模拟
setTimeout(() => {
handler(onResolve);
});
} else {
setTimeout(() => {
handler(onReject);
});
}
});
}
8.all和race的实现
// 当成功时,返回一个数组
// 当有一个失败时,返回失败的结果
static all(promises) {
return new MyPromise((resolve, reject) => {
// 返回值
const values = new Array(promises.length);
// 成功的累加
let resolveCount = 0;
promises.forEach((p, index) => {
// 包一层,防止传入的参数不为promise
MyPromise.resolve(p).then(
(value) => {
resolveCount++;
values[index] = value;
if (resolveCount === promises.length) {
resolve(values);
}
},
(reason) => {
reject(reason);
}
);
});
});
}
// 当有一个先成功时,就返回该值
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach((p) => {
p.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
});
});
}
9.完整代码
(function (window) {
// 定义常量
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
// 定义this,防止this指向发生错误
const _this = this;
// 初始化参数
_this.PromiseState = PENDING;
_this.PromiseResult = null;
// 模拟微队列,用于存放回调
_this.callbacks = [];
// 主要用于更改Promise的状态和结果
function resolve(value) {
// 当状态不是pending时,不处理
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = FULFILLED;
_this.PromiseResult = value;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onResolve(_this.PromiseResult);
});
});
}
}
function reject(reason) {
if (_this.PromiseState !== PENDING) return;
_this.PromiseState = REJECTED;
_this.PromiseResult = reason;
if (_this.callbacks.length) {
// 因为then内部需要晚于Promise的外部的同步任务,即微任务执行,这里采用定时器模拟
setTimeout(() => {
_this.callbacks.forEach((callbackObj) => {
callbackObj.onReject(_this.PromiseResult);
});
});
}
}
// 我们都知道,Promise内部如果抛出异常,则相当于调用了reject
// 这里用trycatch进行捕获
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 返回一个promise
then(onResolve, onReject) {
const _this = this;
// 优化,当onResolve,onReject不是函数的时候
onResolve =
typeof onResolve === "function" ? onResolve : (value) => value;
onReject =
typeof onReject === "function"
? onReject
: (reason) => {
throw reason;
};
return new MyPromise((resolve, reject) => {
function handler(callback) {
// 我们都知道,Promise内部如果抛出异常,则相当于调用了reject
// 这里用trycatch进行捕获
try {
// 当状态为成功时,调用then方法
const result = callback(_this.PromiseResult);
// 此时存在两种情况,
// 1.result为非Promise,则result为Promise的值
// 2.result为Promise
// 2.1根据Promise的结果,来决定当前Promise的最新状态和值
if (result instanceof MyPromise) {
// 简写
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 因为then是同步任务,当Promise内部为异步任务时,会导致then获取不到当前的状态和值,
// 所以当状态为pending时,我们应该将回调存进队列内,当Promise内部执行完毕后,触发回调
if (_this.PromiseState === PENDING) {
// pending状态和fulfilled状态一样,也需要判断结果是否为Promise
_this.callbacks.push({
onResolve() {
handler(onResolve);
},
onReject() {
handler(onReject);
},
});
} else if (_this.PromiseState === FULFILLED) {
// 因为 then内部为微任务,所以用定时器模拟
setTimeout(() => {
handler(onResolve);
});
} else {
setTimeout(() => {
handler(onReject);
});
}
});
}
// 返回一个promise
catch(onReject) {
return this.then(undefined, onReject);
}
// 调用resolve时,会返回一个Promise对象
// 2.1 当resolve的参数为promise时
// 2.2 当resolve的参数不为promise时,其结果就是promise的结果
static resolve(value) {
return new MyPromise((resolve, reject) => {
if (value instanceof MyPromise) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
// 调用reject时,会返回一个Promise对象
// 与resolve不同的是,reject传入的参数是什么,Promise的结果就是什么
static reject(reason) {
return new MyPromise((resovle, reject) => {
reject(reason);
});
}
// 当成功时,返回一个数组
// 当有一个失败时,返回失败的结果
static all(promises) {
return new MyPromise((resolve, reject) => {
// 返回值
const values = new Array(promises.length);
// 成功的累加
let resolveCount = 0;
promises.forEach((p, index) => {
// 包一层,防止传入的参数不为promise
MyPromise.resolve(p).then(
(value) => {
resolveCount++;
values[index] = value;
if (resolveCount === promises.length) {
resolve(values);
}
},
(reason) => {
reject(reason);
}
);
});
});
}
// 当有一个先成功时,就返回该值
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach((p) => {
p.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
});
});
}
}
window.MyPromise = MyPromise;
})(window);
10.总结
- promise有三种状态
- pending
- fulfilled
- rejected
- promise的状态变更,只能从
- pending -> fulfilled
- pending -> rejected
- promise内部为同步任务,当.then内部为微任务
- promise内部
- 若没有resolve或者reject调用,则相当于调用resolve(undefined)
- 若调用resolve,则then触发第一个回调,
- 若调用reject,则then触发第二个回调
- 若没有写then第二个参数,则会一直传递到catch上
- 即若存在多个then,且then都没有第二个参数,则reject会一直传递到外部的catch上
- 若resolve返回的是一个Promise
- 则then的状态由Promise的结果来决定
- 若promise内部抛出异常,则相当于调用了reject