记录Promise学习笔记
下面是模仿过程,我会根据我的理解记录下来
let promise = new Promise((resolve, reject) => {
resolve('成功的 promise')
})
- 系统的Promise是一个类,所以我们应该创建一个类,Promise是立即执行的,所以我们应该在类里面立马执行这个执行器函数,所以写在constructor中,这个执行器接收两个参数函数,一个是成功的回调,一个是失败的回调,Promise有三种状态,同时then方法接收两个回调方法,一个成功的回调,一个是失败的回调,所以初次的框架应该是这样
const PENDING = 'pending' // 等待
const FULFILLED = 'fulfilled' // 成功的状态
const REJECTED = 'rejected' // 失败
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENDING // 状态
value = undefined // 成功回调的值
reason = undefined // 失败的原因
// 箭头函数可以让这两函数this始终指向当前的promise
resolve = (value) => {
// 判断如果状态改变了,将不会往下执行
if (this.status !== PENDING) return
// 如果是reslove, 把它的状态置为成功
this.status = FULFILLED
// 成功的值
this.value = value
}
reject = (reason) => {
// 判断如果状态改变了,将不会往下执行
if (this.status !== PENDING) return
// 如果是reject, 把状态改为失败状态
this.status = REJECTED
// 失败的原因
this.reason = reason
}
then(successCallBack, errorCallBack) {
// 判断状态如果是成功就调用successCallBack的回调,失败的状态就调用errorCallBack
if (this.status === FULFILLED) {
successCallBack(this.value)
} else if(this.status === REJECTED) {
errorCallBack(this.reason)
}
}
}
module.exports = MyPromise
}
let p1 = new MyPromise((resolve, reject) => {
// resolve('成功')
reject('失败')
})
p1.then(res => {
console.log(res);
}, err=> {
console.log(err);
})
可以看到resolve走的是then成功回调,reject走的是then失败的回调
那我们现在可以考虑下,如果是异步情况下,then代码要怎么执行,比如下面这种情况
let p1 = new MyPromise((resolve, reject) => {
// resolve('成功')
// reject('失败')
setTimeout(() => {
resolve('成功')
}, 2000)
})
我们知道setTimeout是个异步代码,那么在还没执行到resolve改变状态就执行到then了,所以在这个时候,状态应该是PENDING,并把then的回调函数保存起来,等resolve执行在把then里面的函数执行
const PENDING = 'pending' // 等待
const FULFILLED = 'fulfilled' // 成功的状态
const REJECTED = 'rejected' // 失败
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENDING // 状态
value = undefined // 成功回调的值
reason = undefined // 失败的原因
// 新增这两行
successCallBack = []
errorCallBack = []
// 箭头函数可以让这两函数this始终指向当前的promise
resolve = (value) => {
// 如果是reslove, 把它的状态置为成功
this.status = FULFILLED
// 成功的值
this.value = value
// 如果是异步的情况下(新增)
while(this.successCallBack.length) this.successCallBack.shift()(this.value)
}
reject = (reason) => {
// 如果是reject, 把状态改为失败状态
this.status = REJECTED
// 失败的原因
this.reason = reason
// 如果是异步的情况下(新增)
while(this.errorCallBack.length) this.errorCallBack.shift()(this.reason)
}
then(successCallBack, errorCallBack) {
// 判断状态如果是成功就调用successCallBack的回调,失败的状态就调用errorCallBack
if (this.status === FULFILLED) {
successCallBack(this.value)
} else if(this.status === REJECTED) {
errorCallBack(this.reason)
} else {
// 新增
// 那我们现在可以考虑下,如果是异步情况下,then代码要怎么执行,那么我们可以把回调存起来,等到执行resolve的时候,再执行回调
this.successCallBack.push(successCallBack)
this.errorCallBack.push(errorCallBack)
}
}
}
module.exports = MyPromise
处理返回值
因为then是可以继续链式调用下去的,所以then函数返回的是一个promise对象
// 其他代码省略。。。。
then(successCallBack, errorCallBack) {
// then函数会返回一个promise
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态如果是成功就调用successCallBack的回调,失败的状态就调用errorCallBack
if (this.status === FULFILLED) {
let x = successCallBack(this.value)
resolve(x)
} else if(this.status === REJECTED) {
errorCallBack(this.reason)
} else {
// 那我们现在可以考虑下,如果是异步情况下,then代码要怎么执行,那么我们可以把回调存起来,等到执行resolve的时候,再执行回调
this.successCallBack.push(successCallBack)
this.errorCallBack.push(errorCallBack)
}
})
return promise2
}
上述的代码只是能满足返回普通值的情况下,如果返回的是promise,那么还得处理一下
声明一个函数,用来判断返回值是普通值还是promise对象
function resolvePromise(x, resolve, reject) {
// 如果返回值是promise
if (x instanceof MyPromise) {
// 就把这个promise对象的值拿到,resolve给下一个then
// x.then(value => resolve(value), reason => reject(reason)),用替换法则就知道为啥要简写成这样了
// 上面代码的简写
x.then(resolve, reject)
} else {
resolve(x)
}
}
then(successCallBack, errorCallBack) {
// then函数会返回一个promise
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态如果是成功就调用successCallBack的回调,失败的状态就调用errorCallBack
if (this.status === FULFILLED) {
let x = successCallBack(this.value)
// 新增
resolvePromise(x, resolve, reject)
// resolve(x)
} else if(this.status === REJECTED) {
errorCallBack(this.reason)
} else {
// 那我们现在可以考虑下,如果是异步情况下,then代码要怎么执行,那么我们可以把回调存起来,等到执行resolve的时候,再执行回调
this.successCallBack.push(successCallBack)
this.errorCallBack.push(errorCallBack)
}
})
return promise2
}
到此,then的成功回调处理返回值已经处理完了,剩下的失败跟等待的同样
resolve = (value) => {
// 如果是reslove, 把它的状态置为成功
this.status = FULFILLED
// 成功的值
this.value = value
// 如果是异步的情况下
while(this.successCallBack.length) this.successCallBack.shift()() // 注意这里没参数了
}
reject = (reason) => {
// 如果是reject, 把状态改为失败状态
this.status = REJECTED
// 失败的原因
this.reason = reason
// 如果是异步的情况下
while(this.errorCallBack.length) this.errorCallBack.shift()() // 注意这里没参数了
}
//省略。。。。。
then(successCallBack, errorCallBack) {
// then函数会返回一个promise
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态如果是成功就调用successCallBack的回调,失败的状态就调用errorCallBack
if (this.status === FULFILLED) {
let x = successCallBack(this.value)
resolvePromise(x, resolve, reject)
// resolve(x)
} else if(this.status === REJECTED) {
let x = errorCallBack(this.reason)
resolvePromise(x, resolve, reject)
} else {
// 那我们现在可以考虑下,如果是异步情况下,then代码要怎么执行,那么我们可以把回调存起来,等到执行resolve的时候,再执行回调
this.successCallBack.push(() => {
let x = successCallBack(this.value)
resolvePromise(x, resolve, reject)
})
this.errorCallBack.push(() => {
let x = errorCallBack(this.reason)
resolvePromise(x, resolve, reject)
})
}
})
return promise2
}
上面的代码可以返回promise跟普通值了
处理捕获
Promise是可以捕获到异常的,所以我们也给我们的promise加上捕获代码
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e.message)
}
}
}
// 省略..........
then(successCallBack, errorCallBack) {
// then函数会返回一个promise
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态如果是成功就调用successCallBack的回调,失败的状态就调用errorCallBack
if (this.status === FULFILLED) {
try {
let x = successCallBack(this.value)
resolvePromise(x, resolve, reject)
} catch (e) {
reject(e)
}
// resolve(x)
} else if(this.status === REJECTED) {
try {
let x = errorCallBack(this.reason)
resolvePromise(x, resolve, reject)
} catch (e) {
reject(e)
}
} else {
// 那我们现在可以考虑下,如果是异步情况下,then代码要怎么执行,那么我们可以把回调存起来,等到执行resolve的时候,再执行回调
this.successCallBack.push(() => {
try {
let x = successCallBack(this.value)
resolvePromise(x, resolve, reject)
} catch (e) {
reject(e)
}
})
this.errorCallBack.push(() => {
try {
let x = errorCallBack(this.reason)
resolvePromise(x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
})
return promise2
}
let p1 = new MyPromise((resolve, reject) => {
// throw new Error('executor')
// resolve('P1成功')
reject('失败')
// setTimeout(() => {
// reject('失败')
// }, 2000)
})
p1.then(res => {
console.log(res);
}, err => {
throw new Error('then 抛出异常')
}).then(res => {
console.log(res);
}, err => {
console.log(err, '0000000');
})
then方法变为可选参数
如果then方法中没有传递参数,那么我们可以帮它造一个
then(successCallBack, errorCallBack) {
successCallBack = successCallBack ? successCallBack: value => value
errorCallBack = errorCallBack ? errorCallBack : reason => { throw reason }
// 省略.........
}
let p1 = new MyPromise((resolve, reject) => {
// throw new Error('executor')
// resolve('P1成功')
reject('失败')
// setTimeout(() => {
// reject('失败')
// }, 2000)
})
p1.then().then().then(res => {console.log(res)}, err=> {console.log(err)})
判断是否循环调用同一个promise
then(successCallBack, errorCallBack) {
successCallBack = successCallBack ? successCallBack: value => value
errorCallBack = errorCallBack ? errorCallBack : reason => { throw reason }
// then函数会返回一个promise
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态如果是成功就调用successCallBack的回调,失败的状态就调用errorCallBack
if (this.status === FULFILLED) {
// 因为这里需要拿到promise2, 所以把它变成异步代码
setTimeout(() => {
try {
let x = successCallBack(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
// resolve(x)
} else if(this.status === REJECTED) {
setTimeout(() => {
try {
let x = errorCallBack(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else {
// 那我们现在可以考虑下,如果是异步情况下,then代码要怎么执行,那么我们可以把回调存起来,等到执行resolve的时候,再执行回调
this.successCallBack.push(() => {
setTimeout(() => {
try {
let x = successCallBack(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
this.errorCallBack.push(() => {
setTimeout(() => {
try {
let x = errorCallBack(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
})
return promise2
}
let p1 = new MyPromise((resolve, reject) => {
// throw new Error('executor')
resolve('P1成功')
// reject('失败')
// setTimeout(() => {
// reject('失败')
// }, 2000)
})
let p = p1.then(res=> {
console.log(res);
return p
}, err=> {
console.log(err);
})
p.then(res => {
console.log(res);
return p
}, err=> {
console.log(err);
})
all方法
因为all是直接由Promise类直接调用的,所以是静态方法
// all方法
static all(array) {
let result = []
return new MyPromise((resolve, reject) => {
for(let i = 0; i < array.length; i++) {
let currData = array[i]
if (currData instanceof MyPromise) {
currData.then(value => result[i] = value, reason => {
console.log(11);
reject(reason)
})
} else {
result[i] = currData
}
}
console.log(22);
resolve(result)
})
}
但是上面的代码还有点问题的,reject的时候返回的结果还是不对,因为这个时候状态总是fulfilled,then里面是异步代码,所以resolve先执行,一旦状态改变了就不会在改变了
let p1 = new MyPromise((resolve, reject) => {
// throw new Error('executor')
//resolve('P1成功')
reject('失败')
// setTimeout(() => {
// resolve('P1成功')
// }, 2000)
})
let p2 = new MyPromise((resolve, reject) => {
resolve('p2成功')
})
MyPromise.all(['a', 'b', p1, p2, 'c']).then(res => {console.log(res, '成功的回调')}, err => {console.log(err, '失败的回调')})
如果是异步代码的时候结果也不对
let p1 = new MyPromise((resolve, reject) => {
// throw new Error('executor')
// resolve('P1成功')
// reject('失败')
setTimeout(() => {
resolve('P1成功')
}, 2000)
})
let p2 = new MyPromise((resolve, reject) => {
resolve('p2成功')
})
MyPromise.all(['a', 'b', p1, p2, 'c']).then(res => {console.log(res, '成功的回调')}, err => {console.log(err, '失败的回调')})
我们得等到所有结果返回后再返回resolve
// all方法
static all(array) {
let result = []
let index = 0
return new MyPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value
index++
if (index === array.length) {
resolve(result)
}
}
for(let i = 0; i < array.length; i++) {
let currData = array[i]
if (currData instanceof MyPromise) {
currData.then(value => addData(i, value), reason => reject(reason))
} else {
addData(i, currData)
}
}
console.log(22);
})
}
resolve方法
resolve方法能调用then方法,证明resolve返回的是promise
// resolve方法
static resolve(value) {
// 如果是promise,直接返回promise
if (value instanceof MyPromise) return value
// 否则返回一个promise
return new MyPromise((resolve, reject) => {
resolve(value)
})
}
}
let p2 = new MyPromise((resolve, reject) => {
resolve('p2成功')
})
MyPromise.resolve(p2).then(res => {console.log(res)})
catch方法跟reject方法
catch(callback) {
return this.then(undefined, callback)
}
// reject方法
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
let p2 = new MyPromise((resolve, reject) => {
// resolve('p2成功')
reject('失败')
})
p2.catch(e => {
console.log(e,'000');
return p1
}).then(res=> {
console.log(res);
}, err => {
console.log(err);
})
finally方法
- 不管是成功还是失败,都会调用finally方法一次
- 可以链式调用then方法,获取当前promise对象最终返回的结果
finally(callback) {
// 不管成功还是失败都会执行,then方法能拿到状态
return this.then((value) => {
callback()
return value
}, (reason) => {
callback()
return reason
})
}
let p2 = new MyPromise((resolve, reject) => {
resolve('p2成功')
// reject('失败')
})
p2.finally(() => {
console.log('finally');
}).then((data=> {console.log(data)}, err => {console.log(err)}))
以上代码确实可以满足需求,但是finally也可以返回promise对象的,如果存在异步的情况下,后面的.then不会等到p1执行完才执行
let p1 = new MyPromise((resolve, reject) => {
// throw new Error('executor')
// resolve('P1成功')
// reject('失败')
setTimeout(() => {
resolve('P1成功')
}, 2000)
})
let p2 = new MyPromise((resolve, reject) => {
resolve('p2成功')
// reject('失败')
})
p2.finally(() => {
console.log('finally');
return p1
}).then((data=> {console.log(data)}, err => {console.log(err)}))
我们需要等到p1执行完后才开始执行后面的then
finally(callback) {
// 不管成功还是失败都会执行,then方法能拿到状态
return this.then((value) => {
// 不管是不是promise,都转成promise
return MyPromise.resolve(callback()).then(() => value)
}, (reason) => {
return MyPromise.resolve(callback()).then(() => {throw reason})
})
}
完整代码
const PENDING = 'pending' // 等待
const FULFILLED = 'fulfilled' // 成功的状态
const REJECTED = 'rejected' // 失败
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e.message)
}
}
status = PENDING // 状态
value = undefined // 成功回调的值
reason = undefined // 失败的原因
successCallBack = []
errorCallBack = []
// 箭头函数可以让这两函数this始终指向当前的promise
resolve = (value) => {
// 判断如果状态改变了,将不会往下执行
if (this.status !== PENDING) return
// 如果是reslove, 把它的状态置为成功
this.status = FULFILLED
// 成功的值
this.value = value
// 如果是异步的情况下
while(this.successCallBack.length) this.successCallBack.shift()()
}
reject = (reason) => {
// 判断如果状态改变了,将不会往下执行
if (this.status !== PENDING) return
// 如果是reject, 把状态改为失败状态
this.status = REJECTED
// 失败的原因
this.reason = reason
// 如果是异步的情况下
while(this.errorCallBack.length) this.errorCallBack.shift()()
}
then(successCallBack, errorCallBack) {
successCallBack = successCallBack ? successCallBack: value => value
errorCallBack = errorCallBack ? errorCallBack : reason => { throw reason }
// then函数会返回一个promise
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态如果是成功就调用successCallBack的回调,失败的状态就调用errorCallBack
if (this.status === FULFILLED) {
// 因为这里需要拿到promise2, 所以把它变成异步代码
setTimeout(() => {
try {
let x = successCallBack(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
// resolve(x)
} else if(this.status === REJECTED) {
setTimeout(() => {
try {
let x = errorCallBack(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else {
// 那我们现在可以考虑下,如果是异步情况下,then代码要怎么执行,那么我们可以把回调存起来,等到执行resolve的时候,再执行回调
this.successCallBack.push(() => {
setTimeout(() => {
try {
let x = successCallBack(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
this.errorCallBack.push(() => {
setTimeout(() => {
try {
let x = errorCallBack(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
})
return promise2
}
catch(callback) {
return this.then(undefined, callback)
}
// finally
finally(callback) {
// 不管成功还是失败都会执行,then方法能拿到状态
return this.then((value) => {
// 不管是不是promise,都转成promise
return MyPromise.resolve(callback()).then(() => value)
}, (reason) => {
return MyPromise.resolve(callback()).then(() => {throw reason})
})
}
// all方法
static all(array) {
let result = []
let index = 0
return new MyPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value
index++
if (index === array.length) {
resolve(result)
}
}
for(let i = 0; i < array.length; i++) {
let currData = array[i]
if (currData instanceof MyPromise) {
currData.then(value => {
console.log(i,value);
addData(i, value)
}, reason => reject(reason))
} else {
console.log(i,currData);
addData(i, currData)
}
}
console.log(22);
})
}
// resolve方法
static resolve(value) {
// 如果是promise,直接返回promise
if (value instanceof MyPromise) return value
// 否则返回一个promise
return new MyPromise((resolve, reject) => {
resolve(value)
})
}
// reject方法
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
}
function resolvePromise(promise2, x, resolve, reject) {
// 判断是否是同一个promise
if (x === promise2) return reject(new TypeError('Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>'))
// 如果返回值是promise
if (x instanceof MyPromise) {
// 就把这个promise对象的值拿到,resolve给下一个then
// x.then(value => resolve(value), reason => reject(reason)),用替换法则就知道为啥要简写成这样了
// 上面代码的简写
x.then(resolve, reject)
} else {
resolve(x)
}
}
module.exports = MyPromise