首页 > 代码库 > ES6-Promise

ES6-Promise

依赖文件地址 :https://github.com/chanceLe/ES6-Basic-Syntax/tree/master/js

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="UTF-8">
  5         <title>[es6]-15-promise</title>
  6         <script src="./js/browser.js"></script>
  7         <script type="text/babel">
  8             /*
  9              * Promise是异步编程的一种解决方案,比传统的回调函数和事件更合理,更强大。
 10              * 由社区最早提出和实现,ES6写入了标准,统一了用法,原生提供了Promise对象。
 11              * 
 12              * 所谓Promise,就是一个容器,里面保存着某个未来才会结束的事件(通常是异步操作)的结果。
 13              * 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。promise提供统一的API,各种异步操作
 14              * 都可以用同样的方法进行处理。
 15              * 
 16              * Promise对象有以下两个特点:
 17              * 1.对象的状态不受外界影响。promise对象代表一个异步操作,有三种状态,pending,Resolved(Fullfilled)和
 18              *   Reject。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这种状态。
 19              * 2.一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending
 20              *   变成Resolved 或 从pending 变成 Rejected。只要这两种情况发生,状态就凝固了,就算再发生了变化,然后添加的
 21              *   回调函数,也会得到promise状态改变时的结果。   这与event完全不同,event的特点是错过了,再监听是得不倒结果的。
 22              * 
 23              * 有了Promise对象,可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。提供统一的接口,使得控制
 24              * 异步操作更加容易。
 25              * 
 26              * Promise也有一些缺点: 
 27              *  1.一旦新建,就会立即执行,无法中途取消
 28              *  2.如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
 29              *  3.当处于pending状态时,无法得知目前进展到哪一个阶段。
 30              * 
 31              * 如果某些事件不断地反复发生,一般来说,使用stream模式比部署Promise更好。
 32              * 
 33              *基本用法:
 34              * es6规定,promise是一个构造函数,用来生成promise实例。
 35              * 
 36              * var promise = new Promise(function(resolve,reject){
 37              *     //some code
 38              *     if( 异步操作成功){
 39              *         resolve(value)
 40              *     }else{
 41              *         reject(error)
 42              *     }
 43              * })
 44              * 
 45              * promise构造函数接受一个函数作为参数,这个函数的两个参数分别是resolve和reject,这是两个函数,由js引擎提供,不用自己部署。
 46              * 
 47              * promise的实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。
 48              * promise.then(function(value){
 49              *     //success
 50              * },function(error){
 51              *     //failure
 52              * })
 53              * 
 54              * then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个是状态变为Reject时调用。
 55              * 第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
 56              */
 57             function timeout(ms){
 58                 return new Promise((resolve,reject)=>{
 59                     setTimeout(resolve,ms,done);
 60                 })
 61             }
 62             timeout(100).then((value)=>{
 63                 console.log(value);
 64             })
 65             
 66             //Promise新建后会立即执行
 67             let promise = new Promise(function(resolve,reject){
 68                 console.log(Promise);
 69                 resolve();
 70             })
 71             promise.then(function(){
 72                 console.log("Resolved")
 73             })
 74             console.log("hi!")
 75             
 76             //Promise.prototype.then()
 77             /*
 78              * promise实例具有then方法,也就是说这个方法定义在原型上。then方法返回的是一个
 79              * 新的promise实例(注意 不是原来那个Promise实例),可以采用链式写法,then方法后面再
 80              * 调用一个then方法。
 81              * 
 82              * 采用链式的then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,
 83              * 有可能返回的还是一个promise对象,这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。
 84              */
 85             
 86             //Promise.prototype.catch()
 87             /*
 88              *  Promise.prototype.catch()是.then(null,rejection)的别名,用于指定发生错误时的回调函数。
 89              * 下面有一个例子:
 90              */
 91             var promise1 = new Promise(function(resolve,reject){
 92                 throw new Error("test");
 93             })
 94             promise1.catch((err)=>{console.log(err)});
 95             
 96             //如果Promise的状态已经变成Resolved,再抛出错误是是无效的。
 97             var promise2 = new Promise(function(resolve,reject){
 98                 resolve("OK");
 99                 throw new Error("test2");
100             })
101             promise2.catch((err)=>{console.log(err)});  //没有执行,已经变成Reslved状态。
102             
103             //Promise对象的错误具有冒泡的性质,会一直向后传递,直到被捕获为止,也就是说,错误总是会被下一个catch语句捕获。
104             //一般来说,不要在then方法里面定义reject状态的回调函数,总是使用catch方法。
105             //catch方法返回的也是一个Promise对象,因此可以配合then方法进行链式调用。
106             
107             //promise.all方法用于将多个promise实例包装成一个新的Promise实例。
108             /*
109              * var p = Promise.all([p1,p2,p3])
110              * 接受一个数组作为参数,数组成员都是Promise实例,如果不是就通过Promise.resolve方法,将参数转为
111              * Promise实例,再进一步处理。 .all()方法的参数可以不是数组,但必须具有Iterator接口。
112              * 
113              * p的状态由p1,p2,p3决定,分两种情况:
114              * 1.只有p1,p2,p3的状态都变成fullfilled,p的状态才会变成fullfilled,此时p1,p2,p3的返回值组成一个数组,传给p的回调函数。
115              * 2.只要p1,p2,p3中有一个beireject,p的状态就变成reject,此时第一个被reject的实例的返回值,会传递给p的回调函数。
116              */
117             
118             /*
119              * Promise.race()
120              * 同样将多个Promise实例,包装成一个新的Promise实例。
121              * var p = Promise.race([p1,p2,p3]);
122              * 只要有一个实例率先改变状态,p的状态就会跟着改变。那个率先改变的Promise实例的返回值,就传递给p的回调函数。
123              * 如果参数不是Promise对象,会通过Promise.resolve方法,转为Promise对象。
124              */
125             
126             /*
127              * Promise.resolve() 
128              * 将现有对象转为Promise对象,Promise.resolve方法就起到这个作用。
129              * 
130              * Promise.resolve("foo")  等价于
131              * new Promise(resolve => resolve("foo"))
132              * 
133              * Promise.resolve参数分为四种情况:
134              *  1.参数是一个promise实例: 原封不动的返回这个实例.
135              *  2.参数是一个thenable对象,指的是具有then方法的对象.
136              *     比如  :
137              *     let thenable = {
138              *          then(resolve,reject){
139              *             resolve(45);
140              *   }
141              *    }
142              *    promise.resolve方法会将这个对象转为Promise对象,然后立即执行thenable对象的then方法。
143              *  3.如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的
144              *     Promise对象,状态为Resolved。
145              */
146               var p = Promise.resolve("hello");
147               p.then(function(s){
148                   console.log(s);
149               })   //hello
150               
151               /*
152                * 4.不带有任何参数
153                * 直接返回一个Resolved状态的Promise对象。
154                * 如果希望得倒一个Promise对象,比较方便的方法就是直接调用Promise.resolve()方法。
155                * 需要注意,立即resolve的Promise对象,是本轮事件循环的结束时,而不是在下一轮事件循环的开始时。
156                */
157               
158               /*
159                * Promise.reject()
160                * 返回一个新的Promise实例,状态为rejected.参数用法与Promise.resolve方法完全一致。
161                */
162               var p2 = Promise.reject("出错了!");   //等同于
163               var p3 = new Promise((resolve,reject)=>reject("出错了!"));
164               p2.then(null,(s)=>{console.log(s)});
165               
166               // 两个有用的附加方法
167               /*
168                * 1.done
169                *  Promise对象的回调链,不管以then方法或catch方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到(
170                * 因为Promise内部的错误不会冒泡到全局)。因此,我们可以提供一个done方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。
171                * done可以提供fullfilled和reject状态的回调函数,也可以不提供任何参数,done都会捕捉到任何可能出现的错误,并向全局抛出。
172                */
173               
174               /*
175                * 2.finally
176                *  用于指定不管Promise对象最后状态如何,都会执行的操作。它与done的最大区别,它接受一个普通的回调函数作为参数,该函数不管怎样都必须执行。
177                */
178               
179               /*
180                * 应用
181                * 1.图片加载
182                *  可以将图片的加载,写成一个Promise,一旦加载完成,Promise 的状态就发生变化。
183                */
184               const preloadImg = function(path){
185                   return new Promise(function(resolve,reject){
186                       var image = new Image();
187                       image.onload = resolve;
188                       image.onerror = reject;
189                       image.src=path;
190                   })
191               }
192               
193               //2.Generator函数与Promise的结合
194               //使用Generator函数管理流程,遇到异步操作的时候,通常返回一个Promise对象。
195               function getFoo(){
196                   return new Promise(function(resolve,reject){
197                       resolve("foo");
198                   })
199               }
200              var g = function*(){
201                  try{
202                      var foo = yield getFoo();
203                      console.log(foo);
204                  }catch(e){
205                      console.log(e);
206                  }
207              }
208              
209              function run(generator){
210                  var it = generator();
211                  function go(result){
212                      if(result.done)  return result.value;
213                      
214                      return result.value.then(function(value){
215                          return go(it.next(value));
216                      },function(error){
217                          return go(it.throw(error));
218                      })
219                  }
220                  go(it.next());
221              }
222              run(g);
223              
224              //上面代码的Generator函数g之中,有一个异步操作getFoo,它返回的就是一个promise对象。
225              //函数run用来处理这个promise对象,并调用下一个next方法。
226         </script>
227     </head>
228     <body>
229     </body>
230 </html>

 

ES6-Promise