码迷,mamicode.com
首页 > 其他好文 > 详细

异步Promise实现

时间:2015-01-13 21:27:56      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:

异步回调的书写往往打乱了正常流的书写方式,在ECMAScript 6中实现了标准的Promise API,旨在

解决控制回调流程的问题。

简单的实现了Promise API:

  

  1     (function(w){
  2             function Promise(fn){
  3                 return this instanceof Promise ? this.init(fn) : new Promise(fn);
  4             }
  5             Promise.fulfill = function(m){return m;};
  6             Promise.reject = function(m){throw m;};
  7             Promise.map = {
  8                 resolve: "onFulfill",
  9                 reject: "onReject"
 10             }
 11             //异步自动生成promise并执行
 12             Promise.resolve = function(fn){
 13                 var p = new Promise();
 14                 setTimeout(function(){
 15                     p.resolve();
 16                 },0);
 17                 if(fn)
 18                     p.callback["onFulfill"] = fn;
 19                 return p;
 20             };
 21             Promise.all = function(){
 22                 var p = new Promise(),
 23                         args;
 24                 var counter = 0,ret = [];//收集结果,并传给p
 25                 var v,fn; //传入的函数,执行该函数,将结果保存至ret
 26                 if(arguments.length > 1){
 27                     args = [].slice.apply(arguments)
 28                 }else if({}.toString.call(arguments[0]) == "[object Array]"){
 29                     args = arguments[0];
 30                 }
 31                 for(var i=0,len=args.length;i<len;i++){
 32                     if(typeof args[i] == "function"){
 33                         args[i] = Promise.resolve(args[i]);
 34 
 35                     }
 36 
 37                     if(isPromise(args[i])) { //如果为promise对象,则将初始函数值传入数组
 38 
 39                     }
 40                     (function(p,i){
 41                         p.then(function(v){
 42                             ret.push(v);
 43 
 44                             if(--counter <= 0){
 45                                 ret.length = len;
 46                                 p.resolve(ret);
 47                             }
 48                         },function(e){
 49                             p.reject(e);
 50                         });
 51 
 52                     })(args[i],i)
 53                     counter++;
 54                 }
 55                 return p;
 56             };
 57             Promise.prototype = {
 58                 init: function(fn){
 59                     var that = this;
 60                     this.state = pending;
 61                     this.callback = {
 62                         onFulfill: Promise.fulfill,
 63                         onReject: Promise.reject
 64                     };
 65                     this.dirty = false;
 66                     this._next = null;
 67                     setTimeout(function(){
 68                         try{
 69                             fn && fn.call(that,that.resolve.bind(that),that.reject.bind(that));
 70                         }catch(e){
 71                             that.reject(e);
 72                         }
 73                     },0)
 74 
 75                 },
 76                 then: function(onFulfill,onReject){
 77                     return post.call(this,onFulfill,onReject);
 78                 },
 79                 wait: function(mills){ //promise链在wait处被分裂成2段
 80                     var p = new Promise(),
 81                             start = new Date().getTime();
 82                     var id = setTimeout(function(){ //传入时间
 83                         p.resolve([this.val,new Date().getTime() - start])
 84                     },mills);
 85                     p.cancel = function(){
 86                         clearTimeout(id);
 87                     }
 88                     return p;
 89                 }
 90             }
 91             function post(onFulfill,onReject,onNotify,onComplete){
 92                 var p = new Promise(),
 93                         that = this;
 94                 if(arguments.length <= 2){
 95                     that._next = p;
 96                     that.callback["onFulfill"] = onFulfill;
 97                     that.callback["onReject"] = onReject;
 98                     this.dirty = true;
 99                 }
100                 return p;
101             }
102             function fire(promise,method,args){
103                 var next = "resolve",val;
104                 if(promise.state == "pending"){console.log(args)
105                     try{
106                         promise.val = val = promise.callback[Promise.map[method]].call(promise,args);
107                         promise.state = method;
108                     }catch(e){
109                         promise.val = val = e;
110                         next = "reject";
111                     }
112 
113                     if(val && isPromise(val)){
114                         val._next = promise._next;
115                     }else{
116                         if(promise._next){
117                             fire(promise._next,next,val);
118                         }
119                     }
120 
121                 }
122                 return promise;
123             }
124             function isPromise(o){
125                 return o && typeof o == "object" && o.then && typeof o.then == "function";
126             }
127             "reject,resolve".replace(/\w+/g,function(m){
128                 Promise.prototype[m] = function(args){
129                     return fire(this,m,args);
130                 }
131             })
132 
133             w.Promise = Promise;
134         })(window)

简易的demo示范:

 1     var getJson = function(url){
 2             return new Promise(function(resolve,reject){
 3                 var xhr = new XMLHttpRequest();
 4                 if(!window.Promise)return;
 5                 xhr.open(get,url);
 6                 xhr.onreadystatechange = function(e){
 7                     if(xhr.readyState == 4){
 8                         if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
 9                             resolve(xhr.responseText);
10                         }else{
11                             reject(new Error(response error));
12                         }
13                     }
14                 };
15                 xhr.onerror = function(e){
16                     reject(new Error(ajax error));
17                 }
18                 xhr.send();
19             });
20         };
21 
22         var body = document.body;
23         var addHtml = function(html){
24             if(typeof  html != string) return;
25             var p = document.createElement(p);
26             p.textContent = html;
27             body.insertBefore(p,loading);
28         };
29         var addHead = function(html){
30             if(typeof html !== string) return;
31             var h = document.createElement(h2);
32             h.textContent = html;
33             body.insertBefore(h,loading);
34         }
35         var log = function(msg){console.log(msg)};
36         var loading = document.getElementById(loading);
37 
38 /*        getJson(‘../json/head.json‘).then(JSON.parse).then(function(html){
39             addHead(html.content);
40             Promise.all(html.urls.map(getJson)).then(function(arr){
41                 arr.forEach(function(content){
42                     addHtml(JSON.parse(content).content);
43                 })
44             }).catch(function(e){
45                 log(‘error in loading content: ‘+ e);
46             })
47         }).catch(function(e){
48             log(‘error: ‘ + e);
49         }).then(function(){
50             loading.style.display = ‘none‘;
51         })*/
52 
53         getJson(../json/head.json).then(JSON.parse).then(function(html){
54             addHead(html.content);
55             var promise = Promise.resolve();
56             html.urls.forEach(function(url,i){
57                 promise = promise.then(function(){
58                     return getJson(url);
59                 }).then(JSON.parse).then(function(html){
60                     addHtml(html.content);
61                 }).catch(function(e){
62                     log(error in loading body: + e );
63                 }).then(function(){
64                     if(i == html.urls.length-1)
65                         loading.style.display = none;
66                 })
67             })
68         })

 

异步Promise实现

标签:

原文地址:http://www.cnblogs.com/accordion/p/4222453.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!