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)
View Code

下面是几种调用

串行

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

并行

 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)})
View Code

创建一个一开始就是 释放状态的 task

Task.resolve(\'data\').then(function(data){
         console.log(data);
     })

 

以上是关于Promise A 规范的一个简单的浏览器端实现的主要内容,如果未能解决你的问题,请参考以下文章

Promise/A+ 规范第 2.2.4 条背后的意图是啥?

promise实现原理

一步一步实现一个Promise A+规范的 Promise

手把手带你实现符合Promise/A+规范的Promise

手把手带你实现符合Promise/A+规范的Promise

when 让你跳出异步回调噩梦 node.js下promise/A规范的使用