Javascript实现promise

Posted 时光游弋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javascript实现promise相关的知识,希望对你有一定的参考价值。

  1 // 三种状态
  2 const PENDING = "pending";
  3 const RESOLVED = "resolved";
  4 const REJECTED = "rejected";
  5 // promise 接收一个函数参数,该函数会立即执行
  6 function MyPromise(fn) {
  7   let _this = this;
  8   _this.currentState = PENDING;
  9   _this.value = undefined;
 10   // 用于保存 then 中的回调,只有当 promise
 11   // 状态为 pending 时才会缓存,并且每个实例至多缓存一个
 12   _this.resolvedCallbacks = [];
 13   _this.rejectedCallbacks = [];
 14 
 15   _this.resolve = function (value) {
 16     if (value instanceof MyPromise) {
 17       // 如果 value 是个 Promise,递归执行
 18       return value.then(_this.resolve, _this.reject)
 19     }
 20     setTimeout(() => { // 异步执行,保证执行顺序
 21       if (_this.currentState === PENDING) {
 22         _this.currentState = RESOLVED;
 23         _this.value = value;
 24         _this.resolvedCallbacks.forEach(cb => cb());
 25       }
 26     })
 27   };
 28 
 29   _this.reject = function (reason) {
 30     setTimeout(() => { // 异步执行,保证执行顺序
 31       if (_this.currentState === PENDING) {
 32         _this.currentState = REJECTED;
 33         _this.value = reason;
 34         _this.rejectedCallbacks.forEach(cb => cb());
 35       }
 36     })
 37   }
 38   // 用于解决以下问题
 39   // new Promise(() => throw Error(‘error))
 40   try {
 41     fn(_this.resolve, _this.reject);
 42   } catch (e) {
 43     _this.reject(e);
 44   }
 45 }
 46 
 47 MyPromise.prototype.then = function (onResolved, onRejected) {
 48   var self = this;
 49   // 规范 2.2.7,then 必须返回一个新的 promise
 50   var promise2;
 51   // 规范 2.2.onResolved 和 onRejected 都为可选参数
 52   // 如果类型不是函数需要忽略,同时也实现了透传
 53   // Promise.resolve(4).then().then((value) => console.log(value))
 54   onResolved = typeof onResolved === ‘function‘ ? onResolved : v => v;
 55   onRejected = typeof onRejected === ‘function‘ ? onRejected : r => throw r;
 56 
 57   if (self.currentState === RESOLVED) {
 58     return (promise2 = new MyPromise(function (resolve, reject) {
 59       // 规范 2.2.4,保证 onFulfilled,onRjected 异步执行
 60       // 所以用了 setTimeout 包裹下
 61       setTimeout(function () {
 62         try {
 63           var x = onResolved(self.value);
 64           resolutionProcedure(promise2, x, resolve, reject);
 65         } catch (reason) {
 66           reject(reason);
 67         }
 68       });
 69     }));
 70   }
 71 
 72   if (self.currentState === REJECTED) {
 73     return (promise2 = new MyPromise(function (resolve, reject) {
 74       setTimeout(function () {
 75         // 异步执行onRejected
 76         try {
 77           var x = onRejected(self.value);
 78           resolutionProcedure(promise2, x, resolve, reject);
 79         } catch (reason) {
 80           reject(reason);
 81         }
 82       });
 83     }));
 84   }
 85 
 86   if (self.currentState === PENDING) {
 87     return (promise2 = new MyPromise(function (resolve, reject) {
 88       self.resolvedCallbacks.push(function () {
 89         // 考虑到可能会有报错,所以使用 try/catch 包裹
 90         try {
 91           var x = onResolved(self.value);
 92           resolutionProcedure(promise2, x, resolve, reject);
 93         } catch (r) {
 94           reject(r);
 95         }
 96       });
 97 
 98       self.rejectedCallbacks.push(function () {
 99         try {
100           var x = onRejected(self.value);
101           resolutionProcedure(promise2, x, resolve, reject);
102         } catch (r) {
103           reject(r);
104         }
105       });
106     }));
107   }
108 };
109 // 规范 2.3
110 function resolutionProcedure(promise2, x, resolve, reject) {
111   // 规范 2.3.1,x 不能和 promise2 相同,避免循环引用
112   if (promise2 === x) {
113     return reject(new TypeError("Error"));
114   }
115   // 规范 2.3.2
116   // 如果 x 为 Promise,状态为 pending 需要继续等待否则执行
117   if (x instanceof MyPromise) {
118     if (x.currentState === PENDING) {
119       x.then(function (value) {
120         // 再次调用该函数是为了确认 x resolve 的
121         // 参数是什么类型,如果是基本类型就再次 resolve
122         // 把值传给下个 then
123         resolutionProcedure(promise2, value, resolve, reject);
124       }, reject);
125     } else {
126       x.then(resolve, reject);
127     }
128     return;
129   }
130   // 规范 2.3.3.3.3
131   // reject 或者 resolve 其中一个执行过得话,忽略其他的
132   let called = false;
133   // 规范 2.3.3,判断 x 是否为对象或者函数
134   if (x !== null && (typeof x === "object" || typeof x === "function")) {
135     // 规范 2.3.3.2,如果不能取出 then,就 reject
136     try {
137       // 规范 2.3.3.1
138       let then = x.then;
139       // 如果 then 是函数,调用 x.then
140       if (typeof then === "function") {
141         // 规范 2.3.3.3
142         then.call(
143           x,
144           y => {
145             if (called) return;
146             called = true;
147             // 规范 2.3.3.3.1
148             resolutionProcedure(promise2, y, resolve, reject);
149           },
150           e => {
151             if (called) return;
152             called = true;
153             reject(e);
154           }
155         );
156       } else {
157         // 规范 2.3.3.4
158         resolve(x);
159       }
160     } catch (e) {
161       if (called) return;
162       called = true;
163       reject(e);
164     }
165   } else {
166     // 规范 2.3.4,x 为基本类型
167     resolve(x);
168   }
169 }

 

以上是关于Javascript实现promise的主要内容,如果未能解决你的问题,请参考以下文章

Javascript中的Promise

在javascript承诺中执行的顺序是什么

基本的 Javascript 承诺实现尝试

前端面试题之手写promise

自定义实现JavaScript中的Promise

自定义实现JavaScript中的Promise