我如何实现Promise A+

栏目: JavaScript · 发布时间: 5年前

内容简介:初步实现Promise:1.实现三种状态:‘pending’, 'fulfilled', 'rejected'2.能够实现then方法两种回调函数的处理
new Promise((resolve, reject) => {
	//异步成功执行resolve,否则执行reject
}).then((res) => {
	//resolve触发第一个回调函数执行	
}, (err) => {
	//reject触发第二个回调函数执行
}).then(res => {
//需要保证then方法返回的依然是promise
//这样才能实现链式调用
}).catch(reason => {

});
//等待所有的promise都成功执行then,
//反之只要有一个失败就会执行catch
Promise.all([promise1, ...]).then();

复制代码

一、小试牛刀

初步实现Promise:

1.实现三种状态:‘pending’, 'fulfilled', 'rejected'

2.能够实现then方法两种回调函数的处理

//promise.js
class Promise{
  //传一个异步函数进来
  constructor(excutorCallBack){
    this.status = 'pending';
    this.value = undefined;
    this.fulfillAry = [];
    this.rejectedAry = [];
    //=>执行Excutor
    let resolveFn = result => {
      if(this.status !== 'pending') return;
      let timer = setTimeout(() => {
        this.status = 'fulfilled';
        this.value = result;
        this.fulfillAry.forEach(item => item(this.value));
      }, 0);
    };
    let rejectFn = reason => {
      if(this.status !== 'pending')return;
      let timer = setTimeout(() => {
        this.status = 'rejected';
        this.value = reason;
        this.rejectedAry.forEach(item => item(this.value))
      })
    };
    try{
      //执行这个异步函数
      excutorCallBack(resolveFn, rejectFn);
    } catch(err) {
      //=>有异常信息按照rejected状态处理
      rejectFn(err);
    }
  }
  then(fulfilledCallBack, rejectedCallBack) {
    //resolve和reject函数其实一个作为微任务
    //因此他们不是立即执行,而是等then调用完成后执行
    this.fulfillAry.push(fulfilledCallBack);
    this.rejectedAry.push(rejectedCallBack);
    //一顿push过后他们被执行
  }
}

module.exports = Promise;

复制代码

测试如下:

let Promise = require('./promise');

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    Math.random()<0.5?resolve(100):reject(-100);
  }, 1000)
}).then(res => {
  console.log(res);
}, err => {
  console.log(err);
})

复制代码

二、 完成链式效果

最大的难点在于链式调用的实现,具体来说就是then方法的实现。

//then传进两个函数
  then(fulfilledCallBack, rejectedCallBack) {
    //保证两者为函数
    typeof fulfilledCallBack !== 'function' ? fulfilledCallBack = result => result:null;
    typeof rejectedCallBack !== 'function' ? rejectedCallBack = reason => {
      throw new Error(reason instanceof Error? reason.message:reason);
    } : null
    //返回新的Promise对象,后面称它为“新Promise”
    return new Promise((resolve, reject) => {
      //注意这个this指向目前的Promise对象,而不是新的Promise
      //再强调一遍,很重要:
      //目前的Promise(不是这里return的新Promise)的resolve和reject函数其实一个作为微任务
      //因此他们不是立即执行,而是等then调用完成后执行
      this.fulfillAry.push(() => {
        try {
          //把then里面的方法拿过来执行
          //执行的目的已经达到
          let x = fulfilledCallBack(this.value);
          //下面执行之后的下一步,也就是记录执行的状态,决定新Promise如何表现
          //如果返回值x是一个Promise对象,就执行then操作
          //如果不是Promise,直接调用新Promise的resolve函数,
          //新Promise的fulfilAry现在为空,在新Promise的then操作后.新Promise的resolve执行
          x instanceof Promise ? x.then(resolve, reject):resolve(x);
        }catch(err){
          reject(err)
        }
      });
      //以下同理
      this.rejectedAry.push(() => {
        try {
          let x = this.rejectedCallBack(this.value);
          x instanceof Promise ? x.then(resolve, reject):resolve(x);
        }catch(err){
          reject(err)
        }
      })
    }) ;
  }
复制代码

测试用例:

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    Math.random()<0.5?resolve(100):reject(-100);
  }, 1000)
})

let p2 = p1.then(result => {
  //执行then返回的是一个新的Promise
  return result + 100;
})
let p3 = p2.then(result => {
  console.log(result);
}, reason => {
  console.log(reason)
})
复制代码

简单画图来模拟一下链式调用的内部流程:

我如何实现Promise A+

有了then方法,catch自然而然调用即可:

catch(rejectedCallBack) {
    return this.then(null, rejectedCallBack);
  }
复制代码

三、Promise.all()

接下来实现Promise.all()

//为类的静态方法,而不是在原型上
static all(promiseAry = []) {
    let index = 0, 
        result = [];
    return new Promise((resolve, reject) => {
      for(let i = 0; i < promiseAry.length; i++){
        promiseAry[i].then(val => {
          index++;
          result[i] = val;
          if( index === promiseAry.length){
            resolve(result)
          }
        }, reject);
      }
    })
  }
复制代码

完整代码

现在手写一个简陋但是功能较为完备的Promise就大功告成了。

class Promise{
  constructor(excutorCallBack){
    this.status = 'pending';
    this.value = undefined;
    this.fulfillAry = [];
    this.rejectedAry = [];
    //=>执行Excutor
    let resolveFn = result => {
      if(this.status !== 'pending') return;
      let timer = setTimeout(() => {
        this.status = 'fulfilled';
        this.value = result;
        this.fulfillAry.forEach(item => item(this.value));
      }, 0);
    };
    let rejectFn = reason => {
      if(this.status !== 'pending')return;
      let timer = setTimeout(() => {
        this.status = 'rejected';
        this.value = reason;
        this.rejectedAry.forEach(item => item(this.value))
      })
    };
    try{
      excutorCallBack(resolveFn, rejectFn);
    } catch(err) {
      //=>有异常信息按照rejected状态处理
      rejectFn(err);
    }
  }
  then(fulfilledCallBack, rejectedCallBack) {
    typeof fulfilledCallBack !== 'function' ? fulfilledCallBack = result => result:null;
    typeof rejectedCallBack !== 'function' ? rejectedCallBack = reason => {
      throw new Error(reason instanceof Error? reason.message:reason);
    } : null

    return new Promise((resolve, reject) => {
      this.fulfillAry.push(() => {
        try {
          let x = fulfilledCallBack(this.value);
          x instanceof Promise ? x.then(resolve, reject ):resolve(x);
        }catch(err){
          reject(err)
        }
      });
      this.rejectedAry.push(() => {
        try {
          let x = this.rejectedCallBack(this.value);
          x instanceof Promise ? x.then(resolve, reject):resolve(x);
        }catch(err){
          reject(err)
        }
      })
    }) ;
  }
  catch(rejectedCallBack) {
    return this.then(null, rejectedCallBack);
  }
  static all(promiseAry = []) {
    let index = 0, 
        result = [];
    return new Promise((resolve, reject) => {
      for(let i = 0; i < promiseAry.length; i++){
        promiseAry[i].then(val => {
          index++;
          result[i] = val;
          if( index === promiseAry.length){
            resolve(result)
          }
        }, reject);
      }
    })
  }
}

module.exports = Promise;

复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python网络编程攻略

Python网络编程攻略

萨卡尔 (Dr.M.O.Faruque Sarker) / 安道 / 人民邮电出版社 / 2014-12-1 / 45.00元

开发TCP/IP网络客户端和服务器应用 管理本地设备的IPv4/IPv6网络接口 使用HTTP和HTTPS协议编写用途多、效率高的Web客户端 编写可使用常见电子邮件协议的电子邮件客户端 通过Telnet和SSH连接执行远程系统管理任务 使用Web服务与流行的网站交互 监控并分析重要的常见网络安全漏洞一起来看看 《Python网络编程攻略》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具