关于Promise当中的一些特性,咱们需求了解并且掌握,今天咱们来依据特性一步一步的完成咱们的Promise源码,更好的了解并且掌握它
1、resolve reject 完成
//html
let p = new Promise((resolve, reject) => {
resolve('OK11');
resolve('OK');
//reject('rrr')
});
console.log(p)
//js
class Promise{
constructor(executor){
let _this = this
_this.PromiseState = 'pending' //用于保存状况
_this.PromiseResult = null //用于保存成果
let resolve = function(data){
_this.PromiseState = 'success'//没有使用箭头函数,this指向要改动
_this.PromiseResult = data
}
let reject = function(data){
_this.PromiseState = 'rejected'
_this.PromiseResult = data
}
executor(resolve,reject)
}
一开始关于
executor(resolve,reject)
这一段不太了解,可以了解为new Promise实例化的时分传入一个函数,放到construtor中进行履行,函数需求传入俩个参数,需求用resolve和reject两个函数作为参数,这里在传入的函数中调用resolve即调用constructor中的resolve
来看下控制台打印成果
2、只能改动一次状况
Promise中只能改动一次状况,所以每次改动状况前判别一下状况是否现已改动了,这个比较简单
//html
let p = new Promise((resolve, reject) => {
resolve('OK11');
resolve('OK');
});
//js
let resolve = function(data){
+ if(_this.PromiseState!='pending') return
...
}
let reject = function(data){
+ if(_this.PromiseState!='pending') return
...
}
现在只会履行一次resolve
3、抛出过错改动
Promise中假如没有改动状况而是抛出过错,需求将状况改动为reject,那么咱们在executor履行的时分捕获一下过错,假如有过错,改动状况
let p = new Promise((resolve, reject) => {
- resolve('OK11');
- resolve('OK');
+ throw 'error'
});
class Promise{
constructor(executor){
+ try {
executor(resolve,reject)
+ } catch (error) {
+ reject(error)
+ }
+ }
4、then完成
当进入到then的时分
promise同步状况下
履行到then的时分状况是现已改动的,then中传入两个函数,咱们依据状况的不同调用不同的函数,调用函数的时分有一个value值,
这个value是履行
resolve('OK')
的时分现已将ok保存到PromiseResult中,所以在then中输出value的时分,其实便是输出PromiseResult
//html
let p = new Promise((resolve, reject) => {
resolve('OK');
});
p.then(value => {
console.log(value)
}, reason=>{
console.warn(reason)
})
//js
+ then(onResolved,onRejected){
+ if(this.PromiseState=='success'){
+ onResolved(this.PromiseResult)
+ }
+ if(this.PromiseState=='rejected'){
+ onRejected(this.PromiseResult)
+ }
}
此刻咱们的OK现已打印出来
5.异步调用时分then中的问题
以下这段代码不会输出ok,因为在then履行的时分,由于事件循环,then调用的时分resolve还未调用,所以在then中
PromiseState
的状况依然未pending,因而不会输出,所以咱们需求加一个判别
let p = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('OK');
},100)
});
p.then(value => {
console.log(value)
}, reason=>{
console.warn(reason)
})
p.then(value => {
console.log(2222)
}, reason=>{
console.warn(reason)
})
关于then履行的时分状况仍未pending的状况,咱们将回调存到回调列表中,
等待resolve调用
的时分再去履行一切回调,之所以用数组保存
,因为可能有多个then回调
constructor(executor){
+ _this.callbacks = []
let resolve = function(data){
+ _this.callbacks.forEach((item)=>{
+ item.onResolve(_this.PromiseResult)
+ })
}
let reject = function(data){
+ _this.callbacks.forEach((item)=>{
+ item.onReject(_this.PromiseResult)
+ })
}
then(onResolve,onReject){
+ if(this.PromiseState=='pending'){//处理resolved异步比then慢履行的时分
+ this.callbacks.push({onResolve,onReject})
+ }
}
完成promise的回来值
假如回来值是一个
非promise
目标,回来状况设置为成功, 假如回来值是一个异常,回来状况设置为失利
咱们知道then中回来的也是一个Promise,所以咱们给then中回来一个Promise,只需求在promise中做两件工作,履行回调,改动状况
假如回来值是一个promise,此刻咱们的promise现已有then办法了,咱们直接用then办法来处理状况的改动即可,最后加上一层try的过错检验,reject的办法相同
let p = new Promise((resolve, reject) => {
resolve(1);
});
let res = p.then(value => {
return new Promise((resolve,reject)=>{
resolve(2)
})
}, reason=>{
console.warn(reason)
})
console.log(p)
console.log(res)
//js
then(onResolve,onReject){
if(this.PromiseState=='pending'){
this.callbacks.push({onResolve,onReject})
}
return new Promise((resolve,reject)=>{
if(this.PromiseState=='success'){
try {
let res = onResolve(this.PromiseResult)//履行回调
if(res instanceof Promise){
res.then((v)=>{//之所以加这一层 是因为promise状况改动了 可是里边的值没输出 所以要加个then,不然就成了promise里边包裹着一个pormise
resolve(v)//改动状况
},(r)=>{
reject(r)//改动状况
})
}else{
resolve(res)//改动状况
}
} catch (error) {
reject(error)
}
}
})
}
履行一下看看
let p = new Promise((resolve, reject) => {
resolve(1);
});
let res = p.then(value => {
return new Promise((resolve,reject)=>{
resolve(2)
})
}, reason=>{
console.warn(reason)
})
console.log(p)
console.log(res)
假如没有判别res instanceof Promise
,第二个then的会输出一个promise
加上判别后的成果
一开始我在判别回来值为promise这个地方一向搞不懂,为啥要履行then,为啥调用resolve,所以在写源码的时分应该多着手打印、debugger输出,下面是我对这段代码的解说
return new Promise((resolve,reject)=>{
...
if (result instanceof Promise) {//假如是 Promise 类型的目标
result.then(v => {
//之所以加这一层 是认为result是一个promise,
// 他的成功和失利决议了外层promise的状况(也便是真正then回来的promise)
//那么他成功 则调用外层的成功
resolve(v);
}, r => {
reject(r);
})
}
本文正在参与「金石计划 . 分割6万现金大奖」