1.promise接收一个函数做为参数
2.promise中有then方法,then方法中可以拿到promise的执行结果
3.promise可以链式调用
class myPromise {
constructor(fn) {
// 在此处执行fn
fn(resolve)
}
// 因为then方法可以实现链式调用,所以then方法返回的还是promise
then() {return this}
}
// 我们来new 一个promise, 我们可以知道promsie在第一秒的时候resolve一个值出去
// 也就是说then方法在promise实例生成一秒后才会有返回结果
let promsie = new myPromse(resolve => {
setTimeout(() => {
resolve(5)
},1000)
})
promise.then(res => {
// 在实例生成一秒后,才有结果返回
console.log(res)
})
/* 我们发现在生成实例时,执行的fn就是我们传进去的函数,而这个函数接收一个resolve作为参数,
不难发现我们传进去的resolve是一个函数,因为resolve在setTimeout中被执行了,那我们就想了,
这个resolve的作用是什么呢?作用把异步函数的返回值拿到,并传到then方法中
这个resolve到底是在哪定义的函数呢? resolve定义在构造函数里比较合适
这个resolve又应该怎么写呢?
我们可以知道的是,在实例生成后一秒,实例resolve出去一个值,这个值就是then放发执行res的值,
那么resolve方法肯定和当前实例的then方法有联系,他们俩怎么样才能联系起来呢?我陷入了深思
..........................
*/
经过上面稀里糊涂的分析,我们的promise长成了这样:
class myPromise {
constructor(fn) {
// 由于resolve是一个实例方法所以我们要把fn中的resolve绑定成当前promise实例
// 不然resolve方法执行的时候this指向会发生错误
fn(this.resolve.bind(this))
}
// 因为then方法可以实现链式调用,所以then方法返回的还是promise
then() {return this}
//
resolve(value) {
}
}
/*因为resolve方法是在实例生成的第一秒执行的,所以在实例生成的0-1秒then方法是拿不到实列的结果的,所以
then方法里肯定做了些神奇的操作,
那我们就想了then方法到底做了哪些操作呢?
我们可以知道的是then方法接收的也是一个方法作为参数,那我们就想到了,我们等resolve执行后再执行then方法
里的函数不就能拿到结果了吗?
那我们应该怎么操作呢?
看过相关promise实现的同学都知道,当我们执行then方法但是拿不到结果的时候,我们就会把then方法中的这个方法
push到一个数组中,
再到resolve执行的时候再拿到这个数组,并依次执行数组中的函数
*/
所以我们的promise现在应该长这个样子
class myPromise {
value = ''; 用于存放promise的reslove值
callbacks = [] ; // 用于存放then中的方法
state = 'padding'; // 用于判断当前promise是否拿到结果
constructor(fn) {
// 由于resolve是一个实例方法所以我们要把fn中的resolve绑定成当前promise实例,不然我们会找不到
// resolve方法执行的时候会找不到当前对象是谁
fn(this.resolve.bind(this))
}
// 因为then方法可以实现链式调用,所以then方法返回的还是promise
then(callback) {
if(this.state === 'padding') {
this.callbacks.push(callback)
} else {
//直接执行res中的方法把promise实例resolve的值带出去
callback(this.value)
}
return this
}
//
resolve(value) {
this.state = 'fullfiled'; // resolve执行的时候改变promise的状态
this.value = value; // 把resolve的值缓存起来,下次调用then方法时直接使用
// 查看当前实例的callbacks中是否有待执行的函数,有的话执行,并带入resolve的值
this.callbacks.forEach(callback => {
callback(this.value)
})
}
}
但是我们不难发现,then方法中返回的this用永远是我们创建的这个实例,这样就导致链式调用的时候,我们拿到的值永远都是我们创建这个实例的resolve值,这不是我们想要的结果,我们想要的结果是then方法处理后返回的结果,我们需要进行下面的处理
class myPromise {
state = 'padding';
callbacks = [];
constructor(fn) {
fn(this.resolve.bind(this))
}
then(fn) {
return new myPromise(resolve => {
this._hander({
resolve: resolve,
fn: fn
})
})
}
_hander(callback) {
if(this.state === 'padding') {
this.callbacks.push(callback)
} else if (typeof callback.fn === 'function'){
let ret = callback.fn(this.value)
callback.resolve(ret)
} else {
callback.resolve(this.value)
}
}
resolve(value) {
this.state = 'fullfiled';
this.value = value;
this.callbacks.forEach( callback => callback.fn(value))
}
}
由上面的代码可知,我们在promise的构造函数中又加了一_handler个实例方法,我们在执行实例的then方法的时候return出去一个新的promise,并且在这个promise中传入当前then方法的回调函数fn和promise需要的形参resolve。
新生成的promise会执行上一个实例的handler的方法,在handler方法中我们判断上一个实例的state的状态,如果是padding我们就往上一个实例中push进去当前的callback,否则我们执行callback中发fn,并把fn的返回值当作新生成的promise值resolve出去,这样我们的链式调用才有了一定的意义。
但是我们发现如果then方法的返回值不是一个value的类型而是一个新的promise时,我们手写的promsie又出现问题了
那我们下面就来解决then方法返回值时一个promise的情况
class myPromise {
state = 'padding';
callbacks = [];
constructor(fn) {
fn(this.resolve.bind(this))
}
then(fn) {
return new myPromise(resolve => {
this._hander({
resolve: resolve,
fn: fn
})
})
}
_hander(callback) {
if(this.state === 'padding') {
this.callbacks.push(callback)
} else if (typeof callback.fn === 'function'){
let ret = callback.fn(this.value)
callback.resolve(ret)
} else {
callback.resolve(this.value)
}
}
resolve(value) {
if(typeof value === 'object'&& typeof value.then === 'function') {
value.then(this.resolve.bind(this))
return;
}
this.state = 'fullfiled';
this.value = value;
this.callbacks.forEach( callback => callback.fn(value))
}
}
我们在resolve函数中加一个判断判断当前的value值是不是一个promise如果是的话,我们执行这个promise的then方法,并且绑定当前实例的reslove。这个resolve的作用很重要,他是为了把ret的值转换成一个value返回出去。这样如果then方法的返回值是一个promise的话,我们在链式调用的时候就能拿到这个promise的返回值了。