原生 js 简单实现 Promise

Promise 的 polyfill

event loop 会出现小差错

  1 ;(function(window) {
  2     function Promise(executor) {
  3         var self = this;
  4         this.status = 'pending';
  5         this.resolveArgs = [];
  6         this.rejectArgs = [];
  7         this.finallyFn = function() {};
  8         
  9         typeof executor === 'function' ? executor.call(window, function() {
 10             self.status = 'fulfilled';
 11             self.resolveArgs = [].slice.call(arguments);
 12         }, function() {
 13             self.status = 'rejected';
 14             self.rejectArgs = [].slice.call(arguments);
 15         }) : false;
 16     }
 17     
 18     Object.defineProperties(Promise, {
 19         resolve: {
 20             value: resolve,
 21             configurable: true,
 22             writable: true
 23         },
 24         
 25         reject: {
 26             value: reject,
 27             configurable: true,
 28             writable: true
 29         },
 30         
 31         race: {
 32             value: function() {},
 33             configurable: true,
 34             writable: true
 35         },
 36         
 37         all: {
 38             value: function() {},
 39             configurable: true,
 40             writable: true
 41         }
 42     });
 43     
 44     Promise.prototype = {
 45         constructor: Promise,
 46         
 47         then: function(onFulfilled, onRejected) {
 48             var res,
 49                 pro = new Promise();
 50             
 51             //用 macrotask 模仿 microtask
 52             setTimeout(function(that) {
 53                 try{
 54                     if(that.status === 'fulfilled') {
 55                         res = onFulfilled.apply(null, that.resolveArgs);
 56                     } else if(that.status === 'rejected') {
 57                         res = onRejected.apply(null, that.rejectArgs);
 58                     }
 59                 } catch(err) {
 60                     pro.status = 'rejected';
 61                     pro.rejectArgs = [err];
 62                     return pro;
 63                 }
 64                 
 65                 if(res instanceof Promise) {
 66                     if(res.status === 'rejected') {
 67                         pro.status = 'rejected';
 68                         pro.rejectArgs = res.rejectArgs;
 69                     } else if(res.status === 'fulfilled') {
 70                         pro.status = 'fulfilled';
 71                         pro.resolveArgs = res.resolveArgs;
 72                     } else {
 73                         pro.status = 'pending';
 74                     }
 75                 } else {
 76                     pro.status = 'fulfilled';
 77                     pro.resolveArgs = [res];
 78                 }
 79             }, 0, this);
 80             
 81             return pro;
 82         },
 83         
 84         catch: function(onRejected) {
 85             return this.status === 'fulfilled' ? this : this.then(undefined, onRejected);
 86         },
 87         
 88         finally: function(onFinally) {
 89             var pro = new Promise();
 90             this.finallyFn = pro.finallyFn = onFinally;
 91             
 92             //用 macrotask 模仿 microtask
 93             setTimeout(onFinally, 0);
 94             return pro;
 95         },
 96     }
 97     
 98     function resolve() {
 99         var pro = new Promise();
100         pro.status = 'fulfilled';
101         pro.resolveArgs = [].slice.call(arguments);
102         return pro;
103     }
104     
105     function reject() {
106         var pro = new Promise();
107         pro.status = 'rejected';
108         pro.rejectArgs = [].slice.call(arguments);
109         return pro;
110     }
111     
112     window.$Promise = window.Promise = Promise;
113 })(window);
114 
115 //测试
116 var p2 = $Promise.resolve("calling next").catch(function (reason) {
117     //这个方法永远不会调用
118     console.log("catch p1!");
119     console.log(reason);
120 }).then(function (value) {
121     console.log("next promise's onFulfilled"); /* next promise's onFulfilled */
122     console.log(value); /* calling next */
123 }, function (reason) {
124     console.log("next promise's onRejected");
125     console.log(reason);
126 });

猜你喜欢

转载自www.cnblogs.com/lalong/p/10517967.html