Promise A 规范的一个简单的浏览器端实现
Posted btg.yoyo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise A 规范的一个简单的浏览器端实现相关的知识,希望对你有一定的参考价值。
简单的实现了一个promise 的规范,留着接下来模块使用。感觉还有很多能优化的地方,有时间看看源码,或者其他大神的代码
主要是Then 函数。回调有点绕人。
1 !(function(win) { 2 3 4 5 function Task(resolver) { 6 if (!resolver || (typeof resolver).toUpperCase() != \'FUNCTION\') { 7 throw \'task arg is function,and is must\'; 8 return; 9 } 10 11 12 if (!(this instanceof Task)) return new Task(resolver); 13 14 var self = this; 15 //PENDING,FULFILLED,REJECTED 16 self.statu = \'PENDING\'; 17 self.callbackok = null; 18 self.callbackreject = null; 19 20 self.value = null; 21 self.reason = null; 22 23 function resolve(data) { 24 self.statu = \'FULFILLED\'; 25 self.value = data || {}; 26 self.callbackok && self.callbackok(self.value); 27 } 28 29 function reject(reason) { 30 self.statu = \'REJECTED\'; 31 self.reason = reason || {}; 32 self.callbackreject && self.callbackreject(self.reason); 33 } 34 35 36 resolver(resolve, reject); 37 38 } 39 40 41 Task.all = function(arr) { 42 43 if (!(arr instanceof Array)) { 44 throw \'arr must be Task Array\'; 45 return; 46 } 47 48 return Task(function(resolve, reject) { 49 var dataarr = {}; 50 var len = arr.length; 51 for (var i = 0; i < len; i++) { 52 (function(c) { 53 console.log(arr[c]); 54 arr[c].then(function(data) { 55 dataarr[c] = data; 56 len--; 57 if (len == 0) { 58 var data = new Array(len); 59 for (var item in dataarr) { 60 data[item] = dataarr[item]; 61 } 62 resolve(data); 63 } 64 65 }, function(error) { 66 reject(error); 67 }) 68 })(i) 69 } 70 }) 71 } 72 73 //创建一个成功状态的Task对象 74 Task.resolve = function(value) { 75 76 return new Task(function(resolve) { 77 resolve(value); 78 }) 79 } 80 81 Task.prototype.then = function(onFulfilled, onRejected) { 82 83 var task = this; 84 85 return Task(function(resolve, reject) { 86 87 function callback(value) { 88 89 var ret = (typeof onFulfilled).toUpperCase() == \'FUNCTION\' && onFulfilled(value) || value; 90 91 if (isThenable(ret)) { 92 ret.then(function(value) { 93 resolve(value); 94 }, function(reason) { 95 reject(reason); 96 }); 97 } else { 98 resolve(ret); 99 } 100 } 101 102 function errorback(reason) { 103 reason = (typeof onRejected).toUpperCase() == \'FUNCTION\' && onRejected(reason) || reason; 104 reject(reason); 105 } 106 107 if (task.statu === \'PENDING\') { 108 task.callbackok = callback; 109 task.callbackreject = errorback; 110 } else if (task.statu === \'FULFILLED\') { 111 callback(task.value); 112 } else if (task.statu === \'REJECTED\') { 113 errorback(task.reason); 114 } 115 116 }); 117 118 } 119 120 var isThenable = function(obj) { 121 return obj && typeof obj[\'then\'] == \'function\'; 122 } 123 124 window.Task = Task; 125 126 })(window)
下面是几种调用
串行
1 var task = new Task(function(resolve, reject) { 2 setTimeout(function() { 3 resolve(\'aaaa\'); 4 }, 100); 5 }) 6 var task1 = function() { 7 return new Task(function(resolve, reject) { 8 setTimeout(function() { 9 resolve(\'bbbb\'); 10 }, 100); 11 }) 12 } 13 var task2 = function() { 14 return new Task(function(resolve, reject) { 15 setTimeout(function() { 16 resolve(\'cccc\'); 17 }, 100); 18 }) 19 } 20 var task3 = function() { 21 return new Task(function(resolve, reject) { 22 setTimeout(function() { 23 reject(\'dddd\'); 24 }, 100); 25 }) 26 } 27 task.then(task1).then(task2).then(task3).then(function(data) { 28 console.log(data) 29 }, function(error) { 30 console.log(data) 31 });
并行
1 var task = new Task(function(resolve, reject) { 2 setTimeout(function() { 3 resolve(\'aaaa\'); 4 }, 100); 5 }) 6 var task2 = new Task(function(resolve, reject) { 7 setTimeout(function() { 8 resolve(\'aaaa\'); 9 }, 100); 10 }) 11 var task3 = new Task(function(resolve, reject) { 12 setTimeout(function() { 13 resolve(\'aaaa\'); 14 }, 100); 15 }) 16 var task4 = new Task(function(resolve, reject) { 17 setTimeout(function() { 18 resolve(\'aaaa\'); 19 }, 100); 20 }) 21 var task5 = new Task(function(resolve, reject) { 22 setTimeout(function() { 23 resolve(\'aaaa\'); 24 }, 100); 25 }) 26 //并行 27 Task.all([task,task2,task3,task4,task5]).then(function(data){ console.log(data)})
创建一个一开始就是 释放状态的 task
Task.resolve(\'data\').then(function(data){ console.log(data); })
以上是关于Promise A 规范的一个简单的浏览器端实现的主要内容,如果未能解决你的问题,请参考以下文章