前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实现一个promise之完成对x的处理并测试

实现一个promise之完成对x的处理并测试

作者头像
wade
发布2020-04-23 16:20:52
6060
发布2020-04-23 16:20:52
举报
文章被收录于专栏:coding个人笔记coding个人笔记
代码语言:javascript
复制
//处理返回结果
function resolvePromise(promise2, x, resolve, reject) {
 //如果promise和x是同一个对象,reject返回TypeError。
 if(promise2 === x){
  return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'));
 };
 //如果被调用多次,只执行第一次,或略其它调用,如果x不是方法,是不会出现多次调用的。
 let called = false;
 //如果x是对象或者方法
 if((typeof x === 'object' && x !== null) || typeof x === 'function'){
  //如果x是一个对象或者函数,取值then = x.then,如果x.then出错,抛出错误执行reject。
  try{
   let then = x.then;
   //如果then是一个方法,用call改变this指向,把resolve和reject当作参数传递。
   // 成功参数y,失败参数r,并调用成功失败函数。
   if(typeof then === 'function'){
    then.call(x, (y) => {
     if(called) return;
     called = true;
     //如果return的是很多个promise,建议递归判断。
     resolvePromise(promise2, y, resolve, reject);
    }, (r) => {
     if(called) return;
     called = true;
     reject(r);
    })
   }else{
    //是对象,直接成功
    resolve(x);
   };
  }catch (e) {
   if(called) return;
   called = true;
   reject(e);
  }
 }else{
  //普通值,直接返回成功
  resolve(x);
 }
};

完成之后,promise官方推荐了一个测试方法,只有通过测试才算符合标准的promise:

https://github.com/promises-aplus/promises-tests

全局安装promises-aplus-tests,然后写上下面的代码,最后执行promises-aplus-tests promise.js

全部通过就算完成了。

代码语言:javascript
复制
Promise.defer = Promise.deferred = function () {
 let dfd = {};
 dfd.promise = new Promise((resolve, reject) => {
  dfd.resolve = resolve;
  dfd.reject = reject;
 });
 return dfd;
};
module.exports = Promise;

附上完成的代码,可以跑看看:

代码语言:javascript
复制
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
//处理返回结果
function resolvePromise(promise2, x, resolve, reject) {
 if(promise2 === x){
  return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'));
 };
 let called = false;
 if((typeof x === 'object' && x !== null) || typeof x === 'function'){
  try{
   let then = x.then;
   if(typeof then === 'function'){
    then.call(x, (y) => {
     if(called) return;
     called = true;
     resolvePromise(promise2, y, resolve, reject);
    }, (r) => {
     if(called) return;
     called = true;
     reject(r);
    })
   }else{
    resolve(x);
   };
  }catch (e) {
   if(called) return;
   called = true;
   reject(e);
  }
 }else{
  resolve(x);
 }
};
class Promise {
 constructor(executor){
  this.state = PENDING;
  this.value = undefined;
  this.reason = undefined;
  this.onResolvedCallbacks = [];
  this.onRejectedCallbacks = [];
  let resolve = (value) => {
   if(this.state === PENDING){
    this.state = FULFILLED;
    this.value = value;
    this.onResolvedCallbacks.forEach(fn => fn());
   }
  };
  let reject = (reason) => {
   if(this.state === PENDING){
    this.state = REJECTED;
    this.reason = reason;
    this.onRejectedCallbacks.forEach(fn => fn());
   }
  };
  try{
   executor(resolve, reject);
  }catch (e) {
   reject(e);
  }
 }
 then(onFulfilled, onRejected){
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : y => y;
  onRejected = typeof onRejected === 'function' ? onRejected : r => {throw r};
  let promise2 = new Promise((resolve, reject) => {
   if(this.state === FULFILLED){
    setTimeout(() => {
     try{
      let x = onFulfilled(this.value);
      resolvePromise(promise2, x, resolve, reject)
     }catch (e) {
      reject(e);
     };
    }, 0);
   };
   if(this.state === REJECTED){
    setTimeout(() => {
     try{
      let x = onRejected(this.reason);
      resolvePromise(promise2, x, resolve, reject)
     }catch (e) {
      reject(e);
     };
    }, 0);
   };
   if(this.state === PENDING){
    this.onResolvedCallbacks.push(() => {
     setTimeout(() => {
      try{
       let x = onFulfilled(this.value);
       resolvePromise(promise2, x, resolve, reject)
      }catch (e) {
       reject(e);
      };
     }, 0);
    });
    this.onRejectedCallbacks.push(() => {
     setTimeout(() => {
      try{
       let x = onRejected(this.reason);
       resolvePromise(promise2, x, resolve, reject)
      }catch (e) {
       reject(e);
      };
     }, 0);
    });
   };
  });
  return promise2;
 }
}
Promise.defer = Promise.deferred = function () {
 let dfd = {};
 dfd.promise = new Promise((resolve, reject) => {
  dfd.resolve = resolve;
  dfd.reject = reject;
 });
 return dfd;
};
module.exports = Promise;

(完)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 coding个人笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档