也谈Promise

最新的ES6标准添加有Promise方法,但自己在项目中一直使用jQuery(jQuery自己实现了不标准的Promise),加上es6标准还没有得到普及,也就懒得学习相关资料。

最近手头上的活少了,本着好好学习,天天向上的宗旨,便查了些资料,学习下Promise。

我们都知道js是单线程的,意味着在同一时间段,浏览器只能解析一段脚本。这很让人抓狂啊。想想你自己,同一时间只能吃零食或看电影,不能边吃零食边看电影,那得多崩溃啊。

许多时候,我们的业务需求需要保证这样的数据流向:A->B->C->...>X

基于事件回调,我们可以把事件一层层嵌套,一层层回调。但这很容易导致回调金字塔。

Promise基于这些类似的业务场景,提供给了我们解决事件回调的方案。

===============================================================

Promise

1.构造一个promise对象

 1 var promise = new Promise(function(resolve, reject) {
 2             // do a thing, possibly async, then…
 3 
 4             if (/* everything turned out fine */) {
 5                 resolve("Stuff worked!");
 6             }
 7             else {
 8                 reject(Error("It broke"));
 9             }
10         });

Promise的构造器接受一个函数作为参数,它会传递这个回调函数两个变量resolve和reject。在回调函数中你可以做一些异步操作,成功之后调用resolve,否则调用reject。

 

2.Promise的使用

1 promise.then(function(result) {
2   console.log(result); // "Stuff worked!"
3 }, function(err) {
4   console.log(err); // Error: "It broke"
5 });

这里有两个回调,第一个回调对应实例化Promise时reslove方法,第二个回调则对应reject方法。当然,这两个函数都是可选的,是否使用基于个人需要。

 

3.Promise的链式调用

Promise强大的地方就在于它不仅可以配平回调金字塔,而且可以链式调用,每一次调用then函数,都会返回一个Promise类。

 1 var promise = new Promise(function(resolve, reject) {
 2   resolve(1);
 3 });
 4  
 5 promise.then(function(val) {
 6   console.log(val); // 1
 7   return val + 2;
 8 }).then(function(val) {
 9   console.log(val); // 3
10 });

这里神奇的地方就在于then函数的返回。如果你返回一个值,它就会被传给下一个then回调;而如果你返回一个Promise对象,则下一个then就会等待这个Promise明确结束(成功或失败)才会失败。

===============================================================

最佳实践

我们有如下需求,需要首先load到数据1,数据1成功返回后才继续load数据2。用Promise来实现,就是下面的代码,大家可以参考学习下

 1 var getData1 = function () {
 2             return new Promise(function (resolve, reject) {
 3                 $.ajax({
 4                     dataType: "json",
 5                     url: 'testData1.json',
 6                     success: function (data) {
 7                         resolve(data);
 8                     },
 9                     error: function (err) {
10                         reject(err);
11                     }
12                 });
13             });
14         }
15         var getData2 = function () {
16             return new Promise(function (resolve, reject) {
17                 $.ajax({
18                     dataType: "json",
19                     url: 'testData2.json',
20                     success: function (data) {
21                         resolve(data);
22                     },
23                     error: function (err) {
24                         reject(err);
25                     }
26                 });
27             });
28         }
29         getData1().then(function (res) {
30             console.log('####data1');
31             console.log(res);
32             return getData2();
33         }).then(function (res) {
34             console.log('####data2');
35             console.log(res);
36         });

 

我把获取数据1和数据2分成两个方法来实现。在getData1的then回调中,返回getData2,这样就能保证load到数据1再去load数据2.

=================================================================================

Promise确实强大,但可惜的是,现在能支持es6特性的浏览器不多。很多情况下,原生的Promise不是我们的首选。

上面讲到的这些特性只是一些基本的特性,它还有许多强大的特性需要我们去挖掘。

假以时日,浏览器端完成统一大战,ES6得到广泛支持,那将是前端界的一大幸事,虽然前路漫漫,但我们依旧翘首以待!

 

posted @ 2015-04-14 16:47  卡布其诺猫  阅读(207)  评论(0编辑  收藏  举报