zoukankan      html  css  js  c++  java
  • ES6新增Promise

    1.promise概念

    ES6 原生提供了 Promise 对象。

    所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。

    Promise 对象有以下两个特点。

    (1)对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。

    (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

    有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。

    Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

     1 var promise = new Promise(function(resolve, reject) {
     2      if (/* 异步操作成功 */){
     3          resolve(value);
     4      } else {
     5          reject(error);
     6      }
     7 });
     8 
     9 promise.then(function(value) {
    10      // success
    11 }, function(value) {
    12      // failure
    13 });        

    2.举个例子

    “小妞妞,嫁给我吧!我发誓,我会对你一辈子好的!”

    “这个嘛,你先去问问我爸爸,我大伯以及我大姑的意思,他们全部都认可你,我再考虑考虑!对了,如果我爸没有答复,大伯他们肯定是不会同意的;如果大伯没有答复,大姑也是不会同意的。”

    传统思维,基于“去搞定岳父→…等待期…结果来了…→去搞定大伯→…等待期…结果来了…→去搞定大姑→…等待期…结果来了…→去搞定女神→…等待期…结果来了…”的思路,中间是很多的嵌套。

     1 男神.请求({
     2    姓名: "岳父",
     3    成功: 男神.继续请求({
     4        姓名: "大伯",
     5        成功: 男神.继续请求({
     6            姓名: "大姑",
     7            成功: 男神.最终请求({
     8                姓名: "女神",
     9                成功: "求婚成功",
    10                失败: "求婚失败"
    11             }),
    12             失败: 男神.继续请求({
    13                姓名: "大姑",
    14                成功: 男神.最终请求({
    15                    姓名: "女神",
    16                    成功: "求婚成功",
    17                    失败: "求婚失败"
    18                 }),
    19                 失败: "求婚失败"
    20             })
    21         }),
    22         失败: 男神.继续请求({
    23            姓名: "大伯",
    24            成功: 男神.继续请求({
    25                姓名: "大姑",
    26                成功: 男神.最终请求({
    27                    姓名: "女神",
    28                    成功: "求婚成功",
    29                    失败: "求婚失败"
    30                 }),
    31                 失败: 男神.继续请求({
    32                    姓名: "大姑",
    33                    成功: 男神.最终请求({
    34                        姓名: "女神",
    35                        成功: "求婚成功",
    36                        失败: "求婚失败"
    37                     }),
    38                     失败: "求婚失败"
    39                 })
    40             }),
    41             失败: "求婚失败"
    42         })
    43     }),
    44     失败: 男神.请求({
    45        姓名: "岳父",
    46        成功: 男神.继续请求({
    47            姓名: "大伯",
    48            成功: 男神.继续请求({
    49                姓名: "大姑",
    50                成功: 男神.最终请求({
    51                    姓名: "女神",
    52                    成功: "求婚成功",
    53                    失败: "求婚失败"
    54                 }),
    55                 失败: 男神.继续请求({
    56                    姓名: "大姑",
    57                    成功: 男神.最终请求({
    58                        姓名: "女神",
    59                        成功: "求婚成功",
    60                        失败: "求婚失败"
    61                     }),
    62                     失败: "求婚失败"
    63                 })
    64             }),
    65             失败: 男神.继续请求({
    66                姓名: "大伯",
    67                成功: 男神.继续请求({
    68                    姓名: "大姑",
    69                    成功: 男神.最终请求({
    70                        姓名: "女神",
    71                        成功: "求婚成功",
    72                        失败: "求婚失败"
    73                     }),
    74                     失败: 男神.继续请求({
    75                        姓名: "大姑",
    76                        成功: 男神.最终请求({
    77                            姓名: "女神",
    78                            成功: "求婚成功",
    79                            失败: "求婚失败"
    80                         }),
    81                         失败: "求婚失败"
    82                     })
    83                 }),
    84                 失败: "求婚失败"
    85             })
    86         }),
    87         失败: "求婚失败"
    88     })
    89 })

     用模拟promise的方式写的函数,但依次执行的触发依然在回调中。我们可能希望得到的代码具有如下与现实世界统一的思维:“搞定岳父→搞定大伯→搞定大姑→搞定女神”,但是,下面的实现却看不出这样的思维。

     1 // 男神的各项参数
     2 var NanShen = {
     3     "身高": 180,
     4     "体重": 80,
     5     "年薪": "200K",
     6     request: function(obj) {
     7         // 成功与否随机决定
     8         // 执行成功的概率为80%
     9         if (Math.random() > 0.2) {
    10             obj.success();
    11         } else {
    12             obj.error();
    13         }
    14     }
    15 };
    16 
    17 var Request = function(names, success) {
    18     var index = 0, first = 0;
    19     var request = function() {
    20         if (names[index]) {
    21             NanShen.request({
    22                 name: names[index],
    23                 success: function() {
    24                     first = 0;
    25                     console.log("成功拿下" + names[index]);
    26                     index++;
    27                     request();
    28                 },
    29                 error: function() {
    30                     if (first == 1) {
    31                         console.log("依旧没能拿下" + names[index] + ",求婚失败");    
    32                         return;
    33                     } else {
    34                         console.log("没能拿下" + names[index] + ",再试一次");    
    35                     }
    36                     first = 1;
    37                     request();    
    38                 }
    39             });    
    40         } else {
    41             success();
    42         }
    43     };    
    44     
    45     request();
    46 };
    47 
    48 Request(["岳父", "大伯", "大姑"], function() {
    49     NanShen.request({
    50         name: "女神",
    51         success: function() {
    52             console.log("女神同意,求婚成功!");
    53         },
    54         error: function() {
    55             console.log("女神不同意,求婚失败!");
    56         }
    57     });
    58 })

    带有promise写法的代码是如下:

     1 // 男神的各项参数
     2 var NanShen = {
     3     "身高": 180,
     4     "体重": 80,
     5     "年薪": "200K",
     6     request: function(obj) {
     7         // 成功与否随机决定
     8         // 执行成功的概率为80%
     9         if (Math.random() > 0.2) {
    10             obj.success();
    11         } else {
    12             obj.error();
    13         }
    14     }
    15 };
    16 
    17 var Request = function(name) {
    18     return new Promise(function(resolve, reject) {
    19         var failed = 0, request = function() {            
    20             NanShen.request({
    21                 name: name,
    22                 success: function() {
    23                     console.log(name + "攻略成功!");
    24                     failed = 0;
    25                     resolve();
    26                 },
    27                 error: function() {
    28                     if (failed == 0) {
    29                         console.log("第一次攻略" + name + "失败,重试一次!");
    30                         failed = 1;
    31                         // 重新攻略一次
    32                         request();                       
    33                     } else {
    34                         console.log("依然没有拿下" + name + ",求婚失败!");
    35                         reject();
    36                     }
    37                 }
    38             });
    39         };
    40         
    41         request();
    42     });
    43 };
    44 
    45 Request("岳父")                                // 搞定岳父,然后...
    46 .then(function() { return Request("大伯"); })  // 搞定大伯,然后...
    47 .then(function() { return Request("大姑"); })  // 搞定大姑,然后...
    48 .then(function() {                            // 长辈们全部KO后,攻略女神
    49     NanShen.request({
    50         name: "女神",
    51         success: function() {
    52             console.log("女神同意,求婚成功!");
    53         },
    54         error: function() {
    55             console.log("女神不同意,求婚失败!");
    56         }
    57     });
    58 });

    通过在函数中合理的设置resolved()和rejected(),然后通过then()单独设置resolved和rejected的具体操作,可以很直观的用同步的方式表示异步的过程

  • 相关阅读:
    SDN原理 OpenFlow协议 -3
    SDN原理 OpenFlow协议 -2
    蓝桥杯----特殊的回文
    hdu-4513吉哥系列故事——完美队形II--最长回文
    蓝桥杯: 基础练习 十六进制转八进制
    母函数模板核心
    杭电ACM hdu 2079 选课时间 (模板)
    杭电ACM hdu 1398 Square Coins
    求用1g、2g、3g的砝码(每种砝码有无穷多个)称出10g的方案有几种
    有1克、2克、3克、4克的砝码各一枚,能称出哪几种重量?
  • 原文地址:https://www.cnblogs.com/little-jelly/p/5737135.html
Copyright © 2011-2022 走看看