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 });