• 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>
  • 相关阅读:
    线程基础1
    组合数学的卡特兰数 TOJ 3551: Game of Connections
    2017ACM/ICPC广西邀请赛-重现赛(感谢广西大学)
    Codeforces Round #430 (Div. 2)
    线代之高斯消元
    牛客网Wannafly模拟赛
    TOJ3039: 材质贴图
    AtCoder Grand Contest 019
    TOJ 3974: Region n条直线m个圆最多将圆分为几个区域
    AIM Tech Round 4 (Div. 2)
  • 原文地址:https://www.cnblogs.com/chengyunshen/p/7191677.html
Copyright © 2020-2023  润新知