1、第一步
- 1.使用promise的时候,接收一个函数类型的参数executor,executor又接收resolve回调函数和reject回调函数。(因为resolve和reject是在executor函数里面去执行的,所以在executor函数中拿不到上面的回调函数,需要通过bind去改变他们的this指向为myPromise。)
- 2.通过状态来控制,当我们多次执行resolve和reject的时候,只以第一次执行为准。
- 3.执行resolve和reject回调函数的时候,是需要接受参数的,而且在.then中也可以拿到。
class myPromise{
constructor(executor){
this.state = 'pending'; // 2.等待态
this.result = null; // 3.
this.reason = null; // 3.
executor(this.resolve.bind(this),this.reject.bind(this))
}
resolve(result){ // 3.
// 2.
if(this.state==='pending'){
this.state = 'fulfilled';
this.result = result; // 3.
}
}
reject(result){ // 3.
// 2.
if(this.state==='pending'){
this.state = 'rejected';
this.reason = reason; // 3.
}
}
}
2、第二步
.then 接收成功和失败两个回调函数
- 1.通过状态机制来控制成功和失败两个回调函数的执行时机
- 2.进行容错处理
- 3.执行resolve和reject回调函数需要等待状态变更后才去执行,需要通过setTimeout套一下模拟异步。
class myPromise{
constructor(executor){
this.state = 'pending';
this.result = null;
this.reason = null;
executor(this.resolve.bind(this),this.reject.bind(this))
}
resolve(result){
if(this.state==='pending'){
this.state = 'fulfilled';
this.result = result;
}
}
reject(result){
if(this.state==='pending'){
this.state = 'rejected';
this.reason = reason;
}
}
then(onFulfilled,onRejected){
// 2.
onFulfilled = typeof onFulfilled === 'function'?onFulfilled:value =>value;
onRejected = typeof onRejected === 'function'?onRejected:reason =>{
throw reason
}
// 1.
if(this.state === 'fulfilled'){
// 3.
setTimeout(()=>{
onFulfilled(this.result)
})
}
if(this.state === 'rejected'){
setTimeout(()=>{
onRejected(this.reason)
})
}
}
}
3、第三步
在promise中执行回调函数是异步执行,在.then中执行回调函数也是异步执行,由于都是异步执行,无法确定谁先执行,所以需要对其进行限制
- 1.有一种情况是在执行.then的时候状态依然是pending,所以需要对pending状态进行处理,否则会出现程序报错
- 2.当状态是pending的时候,将成功或失败的回调函数存储起来,通过数组存储
- 3.当在执行pending的时候,需要将对应的成功或失败回调函数 push 到对应的数组中
- 4.在执行resolve和reject的时候,将其遍历执行(保证状态变更后执行)
class myPromise{
constructor(executor){
this.state = 'pending';
this.result = null;
this.reason = null;
this.onFulfilledCallbacks = []; //2.
this.onRejectedCallbacks = []; //2.
executor(this.resolve.bind(this),this.reject.bind(this))
}
resolve(result){
if(this.state==='pending'){
this.state = 'fulfilled';
this.result = result;
// 4.
this.onFulfilledCallbacks.forEach(callback=>{
callback(result)
})
}
}
reject(result){
if(this.state==='pending'){
this.state = 'rejected';
this.reason = reason;
// 4.
this.onRejectedCallbacks.forEach(callback=>{
callback(reason)
})
}
}
then(onFulfilled,onRejected){
onFulfilled = typeof onFulfilled === 'function'?onFulfilled:value =>value;
onRejected = typeof onRejected === 'function'?onRejected:reason =>{
throw reason
}
if(this.state === 'fulfilled'){
setTimeout(()=>{
onFulfilled(this.result)
})
}
else if(this.state === 'rejected'){
setTimeout(()=>{
onRejected(this.reason)
})
}
else if(this.state === 'pending'){ // 1.
// 3.
this.onFulfilledCallbacks.push(()=>{
setTimeout(()=>{
onFulfilled(this.result)
})
})
// 3.
this.onRejectedCallbacks.push(()=>{
setTimeout(()=>{
onRejected(this.reason)
})
})
}
}
}
4、第四步
实现.then的链式调用
- 需要定义promise2,返回promise2。
class myPromise {
constructor(executor) {
this.state = 'pending';
this.result = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
executor(this.resolve.bind(this), this.reject.bind(this))
}
resolve(result) {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.result = result;
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
}
}
reject(result) {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
}
}
then(onFulfilled, onRejected) {
// 1.
let promise2 = new myPromise((resolve, reject) => {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw reason
}
if (this.state === 'fulfilled') {
setTimeout(() => {
onFulfilled(this.result)
})
}
else if (this.state === 'rejected') {
setTimeout(() => {
onRejected(this.reason)
})
}
else if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
onFulfilled(this.result)
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
onRejected(this.reason)
})
})
}
})
return promise2; // 1.
}
}
5、第五步
为了应对.then的返回值出现的多种情况,封装一个 resolvePromise 函数对其进行处理
- 1.所以我们需要将回调函数的值复制给 x ,然后将 x 作为参数传入 resolvePromise 中去做处理,
- 2.因为我们需要对 x 和 promise2 做比对,所以它接收 promise2 为参数,所以它一共接收4个参数(Promise2、x 以及 promise2 的成功回调和失败回调的函数,我们都做一样的处理。
- 3.这时候我们需要用try catch的方式来捕获异常,如果是异常了就直接抛出错误。
- 4.在执行回调函数的时候,我们也要用try catch的方式,如果执行异常了,直接执行this.reject来抛出异常
class myPromise {
constructor(executor) {
this.state = 'pending';
this.result = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// 4.
try {
executor(this.resolve.bind(this), this.reject.bind(this))
} catch{
this.reject(error)
}
}
resolve(result) {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.result = result;
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
}
}
reject(result) {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
}
}
then(onFulfilled, onRejected) {
let promise2 = new myPromise((resolve, reject) => {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw reason
}
if (this.state === 'fulfilled') {
setTimeout(() => {
// 3.
try {
let x = onFulfilled(this.result); // 1.
resolvePromise(promise2, x, resolve, reject); // 2.
} catch (e){
this.reject(e)
}
})
}
else if (this.state === 'rejected') {
setTimeout(() => {
// 3.
try {
let x = onRejected(this.reason); // 1.
resolvePromise(promise2, x, resolve, reject); // 2.
} catch (e) {
this.reject(e)
}
})
}
else if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
// 3.
try {
let x = onFulfilled(this.result); //1.
resolvePromise(promise2, x, resolve, reject); // 2.
} catch (e) {
this.reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
// 3.
try {
let x = onRejected(this.reason); // 1.
resolvePromise(promise2, x, resolve, reject); // 2.
} catch (e) {
this.reject(e)
}
})
})
}
})
return promise2;
}
}
6、第六步
回调函数它们的返回值需要传入resolvePromise中做单独的处理
- 1.这时then中传入的回调函数不是函数类型的话,要直接返回值
- 2.然后上面判断是不是函数的兼容处理就不需要了。
class myPromise {
constructor(executor) {
this.state = 'pending';
this.result = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this))
} catch {
this.reject(error)
}
}
resolve(result) {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.result = result;
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
}
}
reject(result) {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
}
}
then(onFulfilled, onRejected) {
let promise2 = new myPromise((resolve, reject) => {
// 容错处理 2.
// onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
// onRejected = typeof onRejected === 'function' ? onRejected : reason => {
// throw reason
// }
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
// 1.
if (typeof onFulfilled !== 'function') {
resolve(this.result)
} else {
let x = onFulfilled(this.result);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
this.reject(e)
}
})
}
else if (this.state === 'rejected') {
setTimeout(() => {
try {
// 1.
if (typeof onFulfilled !== 'function') {
resolve(this.reason)
} else {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
this.reject(e)
}
})
}
else if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
// 1.
if (typeof onFulfilled !== 'function') {
resolve(this.result)
} else {
let x = onFulfilled(this.result);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
this.reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
// 1.
if (typeof onFulfilled !== 'function') {
resolve(this.result)
} else {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
this.reject(e)
}
})
})
}
})
return promise2;
}
}
7、第七步
⭐️ 封装resolvePromise方法:(为了解决 .then 的返回值可能有多种类型:a.返回的是promise2;b.返回一个A+规范promise对象;(例如:我们手写的prmise);c.返回其他规范的promise对象;(返回thenable对象函数,不管是什么规范,它们都支持then属性);d.返回普通的值。)
- 1.首次我们判断 x 和 promise2 是不是指向一个对象,如果指向一个对象的话,就会陷入死循环,所以我们要抛出异常。
- 2.接下来我们判断 x 是不是符合A+规范的promise,如果是的话,我们就在then中拿到返回值,因为它的返回值有可能依然是promise对象,所以我们要传入resolvePromise中做递归处理。
- 3.接下来我们判断它是不是符合其他规范的promise,如何判断其他规范的promise? 首先要判断x是否为对象或函数,其次判断x.then是否为函数,如果都是的话,它就是符合其他规范的promise.所以我们首先判断它是不是对象或函数,如果是的话,我们就将x.then赋值给then,接着我们看then是不是函数类型,如果是的话,我们就将它的this指向为x,然后拿到它的返回值y值传入resolvePromise函数中做递归处理,当发生异常的时候直接抛出异常,
- 4.而且我们注意到,其他规范的promise有可能多次调用多次执行,所以我们需要给它们加锁,我们定义一个锁called为false,当执行then的时候,我们将状态变更为true,这样就保证了它们只执行一次。
function resolvePromise(promise2, x, resolve, reject) {
// ⭐️ 1.
if (x === promise2) {
throw new TypeError('promise error')
}
// ⭐️ 2.
if (x instanceof myPromise) {
x.then(y => {
resolvePromise(promise2, x, resolve, reject)
}, reject);
}
// ⭐️ 3.
else if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) {
try {
let then = x.then;
} catch (e) {
return reject(e);
}
if (typeof then === 'function') {
let called = false; // 4.
try {
then.call(
x,
y => {
if (called) return; // 4.
called = true; // 4.
resolvePromise(promise2, y, resolve, reject);
},
r => {
if (called) return;// 4.
called = true; // 4.
reject(r);
}
)
} catch (e) {
if (called) return; // 4.
called = true; // 4.
reject(e)
}
} else {
resolve(x);
}
} else {
return resolve(x);
}
}
第八步:完整版手写myPromise
// 2.封装 resolvePromise 方法
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
throw new TypeError('promise error')
}
if (x instanceof myPromise) {
x.then(y => {
resolvePromise(promise2, x, resolve, reject)
}, reject);
}
else if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) {
try {
let then = x.then;
} catch (e) {
return reject(e);
}
if (typeof then === 'function') {
let called = false;
try {
then.call(
x,
y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
r => {
if (called) return;
called = true;
reject(r);
}
)
} catch (e) {
if (called) return;
called = true;
reject(e)
}
} else {
resolve(x);
}
} else {
return resolve(x);
}
}
// 1.手写promise
class myPromise {
constructor(executor) {
this.state = 'pending';
this.result = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch {
this.reject(error)
}
}
resolve(result) {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.result = result;
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
}
}
reject(reason) {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
}
}
then(onFulfilled, onRejected) {
let promise2 = new myPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
if (typeof onFulfilled !== 'function') {
resolve(this.result)
} else {
let x = onFulfilled(this.result);
resolvePromise(promise2, x, resolve, reject)
}
} catch (e) {
reject(e);
}
})
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
if (typeof onRejected !== 'function') {
resolve(this.reason)
} else {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject)
}
} catch (e) {
reject(e);
}
})
} else if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
if (typeof onFulfilled !== 'function') {
resolve(this.result)
} else {
let x = onFulfilled(this.result);
resolvePromise(promise2, x, resolve, reject)
}
} catch (e) {
reject(e);
}
})
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
if (typeof onRejected !== 'function') {
resolve(this.reason)
} else {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject)
}
} catch (e) {
reject(e);
}
})
})
}
})
return promise2;
}
}
// 3.调用封装的 myPromise
let p = new myPromise((resolve, reject) => {
setTimeout(function () {
// const num = Math.floor(Math.random()*100);
const num = 6;
if (num <= 50) {
resolve(num);
} else {
reject('大于50');
}
}, 2000);
});
p.then((data) => {
console.log('执行resolved:', data);
}, (err) => {
console.log('执行rejected', err);
})