从构造函数开始
- Promise就是一个类,在执行这个类的时候需要传递一个执行器进去,执行器会立即执行。
- Promise中有三种状态 分别为:成功
失败fulfilled
等待rejected
,一旦状态确定就不可更改。pending
//Promise 类核心逻辑实现
const PENDING = 'pending';//等待
const FULFILLED = 'filfulled';//成功
const REJECTED = 'rejected';//失败
class Promise {
//构造函数
constructor(executor){
//try catch为了捕获执行器中的错误 从而抛出异常
try{
//执行器:立即执行
executor(this.resolve,this.reject)
}catch(e){
this.reject(e)
}
}
//promise状态:先定义为peding,在resolve和reject中改变状态
status = PENDING;
//成功之后的值
value = undefined;
//失败后的原因
reason = undefined;
//成功回调函数队列
successCallback = [];
//失败回调函数队列
failCallback = [];
}
module.exports = Promise
resolve属性的定义
resolve属性用来修改Promise的状态:pending => fulfilled
//构造函数中
resolve = value =>{
//如果不是等待,则阻止程序向下执行
if(this.status !=== 'pending') return;
//将状态更改为成功
this.status = FULFILLED
//保存成功之后的值
this.value = value
//判断成功回调是否存在 如果存在 => 调用:调用完后删除并返回第一个回调的值
while(this.successCallback.length) this.successCallback.shift()()
}
reject属性的定义
reject属性用来修改Promise的状态:pending => rejected
//构造函数中
reject = reason => {
//如果状态不是等待,阻止程序向下执行
if(this.status !== 'pending') return;
//将状态更改为失败
this.status = REJECTED
//保存失败之后的原因
this.reason = reason
//判断失败回调是否存在 如果存在 调用
white(this.failCallback.length) this.failCallback.shift()()
}
then方法的实现
- then方法是被定义在原型对象中的。
- then支持两个参数,分别是成功和失败的回调,而且这两个参数可传可不传。
- then方法内部做的事情就是判断状态:如果状态是成功,调用成功的回调函数 ,如果状态是失败,则调用失败回调函数。
- 因为有异步任务的情况,并且支持多个回调,所以我们需要对回调函数采用数据进行储存,所以上面定义了失败和成功的回调函数队列。
- then的返回结果也是Promise对象
//构造函数中
then(successCallback,failCallback){
//当调用then方法的时候不传递参数,则Promise状态会依次向后传递,直到传递给有回调的then方法
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason }
let promise2 = new Promise((resolve,reject) => {
let that = this
if(this.status === FULFILLED){
//为了变为异步操作
setTimeout(()=>{
//try catch为了捕获错误,抛出异常
try{
let x = successCallback(this.value)
//判断x的值是普通值还是Promise对象:如果是普通值,直接调用resolve / 如果是Promise对象,查看Promise对象返回的结果。
//然后再根据Promise对象返回的结果,决定调用resolve 还是调用reject
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
}else {
//有异步任务时:等待
//将成功回调和失败回调储存起来
this.successCallback.push(()=>{
//为了变为异步操作
setTimeout(()=>{
//try catch为了捕获错误,抛出异常
try{
let x = successCallback(this.value)
//判断x的值是普通值还是Promise对象:如果是普通值,直接调用resolve / 如果是Promise对象,查看Promise对象返回的结果。
//然后再根据Promise对象返回的结果,决定调用resolve 还是调用reject
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
});
this.failCallback.push(()=>{
//为了变为异步操作
setTimeout(()=>{
//try catch为了捕获错误,抛出异常
try{
let x = successCallback(this.value)
//判断x的值是普通值还是Promise对象:如果是普通值,直接调用resolve / 如果是Promise对象,查看Promise对象返回的结果。
//然后再根据Promise对象返回的结果,决定调用resolve 还是调用reject
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
})
}
})
return promise2;
}
function resolvePromise(promise2,x,resolve,reject){
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if(x instanceof Promise){
//Promise对象
x.then(resolve,reject)
}else {
//普通值
resolve(x)
}
}
catch方法的实现
- catch方法用来处理当前这个Promise最终的状态为失败的情况。
- 当我们调用then方法时 是可以不传递失败回调的 那么失败回调就会被catch捕获并传入catch方法的回调函数。
- catch不是静态方法,需要定义在Promise的原型上
//构造函数中
catch(failCallback){
return this.then(undefined,failCallback)
}
finally方法的实现
- 无论当前的这个Promise对象是成功的还是失败的 finally当中的函数总会被执行一次。
- finally方法的后面我们可以链式调用then方法 来得到当前这个Promise最终返回的结果。
- finally不是静态方法,需要定义在Promise的原型上
- 需要实现链式调用
//构造函数中
finally(callback){
//调用then方法来得到当前Promise的状态
//因为then方法就返回一个Promise,所以直接return
//要等待异步操作完成后,后面的then才能执行
return this.then(value => {
//如果callback返回值是普通值,那么就转换成Promise等待执行完成,后面的then再执行,如果返回的是Promise 还是等待执行完成在执行
return Promise.resolve(callback()).then(()=>value)
},reason => {
return Promise.resolve(callback()).then(()=>{ throw reason })
})
}
Promise.resolve方法的实现
- Promise.resolve 的作用就是将里面的值转化为promise对象。
- Promise.resolve 是一个静态方法。
//构造函数中
static resolve(value){
//判断是普通值还是Promise对象,如果是Promise对象就原封不动的放回出去,如果是普通值,那就创建一个Promise将普通值包裹进去返回出去。
if(value instanceof Promise) return value;
return new Promise(resolve => resolve(value));
}
Promise.reject方法的实现
- Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致
- Promise.reject是一个静态方法。
// Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。
// 这一点与Promise.resolve方法不一致
static reject(reason) {
return new Promise((undefined, reject) => reject(reason));
}
Promise.all方法的实现
- Promise.all方法是解决异步并发问题的,它允许我们按照异步调用的顺序来执行异步方法。
- Promise.all是一个静态方法,接收一个数组作为参数。
- Promise.all 后面也可以.then链式调用。
//构造函数中
static all(array){
//准备一个结果数组
let result = [];
let index = 0;
//Promise.all 后面也可以.then 所以先返回个Promise对象
return new Promise((resolve,reject) => {
//向结果数组中添加返回值
function addData(key,value){
result[key] = value
index ++;
//for循环是同步执行循环体的,所以我们必须等待异步操作完成之后才能去返回结果
// 如果index 等于 数组的长度,代表所有的操作已经完毕,就可以返回结果了
if(index === array.length){
resolve(result);
}
}
//通过循环的方式,循环进来的数据,在循环过程中判断了循环当前值,判断其是普通值还是Promise对象
for(let i=0;i<array.length;i++){
let current = array[i]
//判断当前的值是普通值还是Promise对象
if(current instanceof Promise){
//注:在执行过程中别忘记有异步任务,for循环是不会等待异步操作的,所以当我们调用resolve的时候,还没有执行完,所以结果中会有空值。
//Promise对象:先执行Promise对象,如果执行成功调用addData方法,反之reject()
current.then(value => addData(i,value),reason => reject(reason))
}else {
//普通值:对应放入结果数组中
addData(i,array[i])
}
}
})
}
Promise.race方法的实现
// race方法
static race (array) {
// race方法,取数组中第一个返回的结果,无论成功或者失败
return new Promise((resolve, reject) => {
array.forEach(current => {
if (current instanceof Promise) {
// promsie对象,返回成功或者失败的结果
current.then(value => resolve(value), reason => reject(reason))
} else {
// 普通值 ,直接返回
resolve(current)
}
})
})
}
完整代码
const PENDING = 'pending';//等待
const FULFILLED = 'filfulled';//成功
const REJECTED = 'rejected';//失败
class Promise {
constructor(executor){
try{
executor(this.resolve,this.reject)
}catch(e){
this.reject(e)
}
}
status = PENDING;
value = undefined;
reason = undefined;
successCallback = [];
failCallback = [];
resolve = value =>{
if(this.status !=== 'pending') return;
this.status = FULFILLED
this.value = value
while(this.successCallback.length) this.successCallback.shift()()
}
reject = reason => {
if(this.status !== 'pending') return;
this.status = REJECTED
this.reason = reason
white(this.failCallback.length) this.failCallback.shift()()
}
then(successCallback,failCallback){
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason }
let promise2 = new Promise((resolve,reject) => {
let that = this
if(this.status === FULFILLED){
setTimeout(()=>{
try{
let x = successCallback(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
}else {
this.successCallback.push(()=>{
setTimeout(()=>{
try{
let x = successCallback(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
});
this.failCallback.push(()=>{
setTimeout(()=>{
try{
let x = successCallback(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
})
}
})
return promise2;
}
function resolvePromise(promise2,x,resolve,reject){
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if(x instanceof Promise){
x.then(resolve,reject)
}else {
resolve(x)
}
}
catch(failCallback){
return this.then(undefined,failCallback)
}
finally(callback){
return this.then(value => {
return Promise.resolve(callback()).then(()=>value)
},reason => {
return Promise.resolve(callback()).then(()=>{ throw reason })
})
}
static resolve(value){
if(value instanceof Promise) return value;
return new Promise(resolve => resolve(value));
}
static reject(reason) {
return new Promise((undefined, reject) => reject(reason));
}
static race (array) {
return new Promise((resolve, reject) => {
array.forEach(current => {
if (current instanceof Promise) {
current.then(value => resolve(value), reason => reject(reason))
} else {
resolve(current)
}
})
})
}
static all(array){
let result = [];
let index = 0;
return new Promise((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 current = array[i]
if(current instanceof Promise){
current.then(value => addData(i,value),reason => reject(reason))
}else {
addData(i,array[i])
}
}
})
}
}
module.exports = Promise