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的具体操作,可以很直观的用同步的方式表示异步的过程

原文地址:https://www.cnblogs.com/little-jelly/p/5737135.html