使用 Promises 编写更优雅的 JavaScript 代码

  你可能已经无意中听说过
Promises,很多人都在讨论它,使用它,但你不知道为什么它们如此特别。难道你不能使用回调么?有什么了特别的?在本文中,我们一起来看看 Promises
是什么以及如何使用它们写出更优雅的 JavaScript
代码。

您可能感兴趣的相关文章

Promises 易于阅读


  比如说我们想从 HipsterJesus 的API中抓取一些数据并将这些数据添加到我们的页面中。这些 API
的响应数据形式如下:

?





1

2

3

4

5

6

  "text": "<p>Lorem ipsum...</p>"

  "params": { 

  "paras": 4, 

  "type": "hipster-latin"

}} 

  要使用回调的话,我们通常要写如下形式的东西:

?





1

2

3

$.getJSON(http://hipsterjesus.com/api/, function(data) { 

  $(‘body‘).append(data.text); 

}); 

  如果你有 jQuery
的使用经历,你会认出我们创建了一个 GET 请求并且希望响应内容是 JSON。我们还传递了一个回调函数来接受响应的 JSON,以将数据添加到文档中。

  另外一种书写方法是使用 getJSON 方法返回的 promise 对象。你可以直接在这个返回对象上绑定一个回调。

?





1

2

3

var
promise = $.getJSON(http://hipsterjesus.com/api/);promise.done(function(data) { 

  $(‘body‘).append(data.text); 

}); 

  在上面的回调例子中,当响应成功时它将 API 请求的结果添加到文档中。但当响应失败是会发生什么呢?我们可以在我们的 promise
上绑定一个失败处理器。

?





1

2

3

4

var
promise = $.getJSON(http://hipsterjesus.com/api/);promise.done(function(data) { 

  $(‘body‘).append(data.text);});promise.fail(function() { 

  $(‘body‘).append(‘<p>Oh no, something went wrong!</p>‘); 

}); 

  大多数人删掉了 promise 变量,这样更简洁,一眼就能看出代码的作用。

?





1

2

3

4

$.getJSON(http://hipsterjesus.com/api/).done(function(data) { 

  $(‘body‘).append(data.text);}).fail(function() { 

  $(‘body‘).append(‘<p>Oh no, something went wrong!</p>‘); 

}); 

  jQuery 也包含一个一直发生的事件处理器,不论请求成功失败都会被调用。

?





1

2

3

4

5

$.getJSON(http://hipsterjesus.com/api/).done(function(data) { 

  $(‘body‘).append(data.text);}).fail(function() { 

  $(‘body‘).append(‘<p>Oh no, something went wrong!</p>‘);}).always(function() { 

  $(‘body‘).append(‘<p>I promise this will always be added!.</p>‘); 

}); 

  通过使用promise,回调的顺序是按预期的。我们能确保正常回调先被调用,然后是失败回调,最后是一直发生的回调。

更好的 API

  比如说我们想创造一个 HipsterJesus API 的封装对象。我们会添加一个方法——html,它将来自 API 的 HTML
数据返回。与之前设置一个回调处理器来解析请求不同,我们可以让方法返回一个 promise 对象。

?





1

2

3

4

5

6

var
hipsterJesus = { 

  html: function() { 

    return
$.getJSON(http://hipsterjesus.com/api/).then(function(data) { 

      return
data.text; 

    }); 

}}; 

  这个做法很酷,这样我们可以绕过 promise 对象而不必担心何时或如何解析它的值。任何需要 promise
返回值的代码只需注册一个成功响应回调即可。

then方法允许我们修改promise的结果并将其传递给链中的下一个处理器。这意味现在我们可以这样使用新的API:

?





1

2

3

hipsterJesus.html().done(function(html) { 

  $("body").append(html); 

}); 

  直到最近,AngularJS 出现了一个杀手级特性,模板可以直接绑定到promise。在Angular的控制器中,像这样:

?





1

$scope.hipsterIpsum = $http.get(http://hipsterjesus.com/api/); 

  这样,在模板中写 {{ hipsterIpsum.text }} 就很简单了。当 promise 解析后,Angular 不需要自动更新视图。不幸的是
Angular 团队已经放弃了这一特性。现在,它可以通过调用 $parseProvider.unwrapPromises(true)
来启用。我希望Angular已经其他框架一直包含此特性(我会一直留意)。

链式调用

  Promise 最出彩的部分是你可以将它们串联起来。比如说我们想添加一个方法到一个返回一段数组的 API。

?





1

2

3

4

5

6

7

8

9

10

11

12

13

var
hipsterJesus = { 

 

  html: function() { 

    return
$.getJSON(http://hipsterjesus.com/api/).then(function(data) { 

      return
data.text; 

    }); 

  }, 

 

  paragraphs: function() { 

    return
this.html().then(function(html) { 

      return
html.replace(/<[^>]+>/g, "").split(""); 

    }); 

  }}; 

  我们以上面的方式这种 HTML
方法,我们用它在 paragraphs
方法中。因为promise回调函数的返回值将传递给链中的下一个回调,我们能够在通过它们时自由地创建小的、功能性的方法来改变数据。

  我们可以按需求任意次串联promise。让我们添加一个。

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

var
hipsterJesus = { 

 

  html: function() { 

    return
$.getJSON(http://hipsterjesus.com/api/).then(function(data) { 

      return
data.text; 

    }); 

  }, 

 

  paragraphs: function() { 

    return
this.html().then(function(html) { 

      return
html.replace(/<[^>]+>/g, "").split(""); 

    }); 

  }, 

 

  sentences: function() { 

    return
this.paragraphs().then(function(paragraphs) { 

      return
[].concat.apply([], paragraphs.map(function(paragraph) { 

        return
paragraph.split(/. /); 

      })); 

    }); 

  }};   

多个调用

  可能 promise 最显著的特点是调用多个 API 的能力。当使用回调时,如果你需要同时创建两个API调用时会发生什么呢?你可能会这样写:

?





1

2

3

4

5

6

7

8

9

10

11

var
firstData = null;var
secondData = null;var
responseCallback = function() { 

 

  if
(!firstData || !secondData) 

    return

 

  // do something}$.get("http://example.com/first", function(data) { 

  firstData = data; 

  responseCallback();});$.get("http://example.com/second", function(data) { 

  secondData = data; 

  responseCallback(); 

}); 

  使用 promise 的话,这就简单多了:

?





1

2

3

4

5

var
firstPromise = $.get("http://example.com/first"); 

var
secondPromise = $.get("http://example.com/second"); 

$.when(firstPromise, secondPromise).done(function(firstData, secondData) { 

  // do something 

}); 

  这里我们使用 when 方法,将其绑定到一个供两个请求都完成时调用的处理器上。

结论

  这就是 Promise。希望你马上就想到一些可以用 Promise 实现的的可怕的事情。你最喜欢使用它们的方式是什么?在评论中告诉我吧!

  *注:为简单起见,本文使用了jQuery的延期执行。jQuery
的 Deferred对象 和 Promises/A+的规范 间有细微的差别,这个规范更标准。更多信息,查看 jQuery维基 上的问答。

您可能感兴趣的相关文章

译文链接:使用 Promises 模式编写更好的 JavaScript 代码

编译来源:梦想天空 ◆ 关注前端开发技术
◆ 分享网页设计资源

本文来自【梦想天空(http://www.cnblogs.com/lhb25/)】

使用 Promises 编写更优雅的 JavaScript 代码,码迷,mamicode.com

时间: 2025-01-01 21:35:51

使用 Promises 编写更优雅的 JavaScript 代码的相关文章

编写更好的jQuery代码(转)

这是一篇关于jQuery的文章,写到这里给初学者一些建议. 原文地址:http://flippinawesome.org/2013/11/25/writing-better-jquery-code/ 现在已经有很多文章讨论jQuery和JavaScript的性能问题,然而,在这篇文章中我计划总结一些提升速度的技巧和一些我自己的建议来改善你的jQuery和JavaScript代码.更好的代码意味着更快的应用程序,快速渲染和反应性意味着一个更好的用户体验. 首先,我们要记住最重要的一点是:jQuer

编写更好的jQuery代码的建议

编写更好的jQuery代码的建议 2013/12/05 | 分类: WEB前端, 开发 | 15 条评论 | 标签: JQUERY 分享到:125 本文由 伯乐在线 - yanhaijing 翻译自 Mathew Carella.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. 讨论jQuery和javascript性能的文章并不罕见.然而,本文我计划总结一些速度方面的技巧和我本人的一些建议,来提升你的jQuery和javascript代码.好的代码会带来速度的提升.快速渲染和响应意味着更好的

[label][翻译][JavaScript-Translation]七个步骤让你写出更好的JavaScript代码

7 steps to better JavaScript 原文:http://www.creativebloq.com/netmag/7-steps-better-javascript-51411781七个步骤让你写出更好的JavaScript代码 随着浏览器的性能提升,新的HTML5 APIS也在不断地被应用,JavaScript在web使用中不断增长.然而,一行糟糕的代码就有可能会影响到整个网站,产生糟糕的用户体验和造成潜在客户的流失. 开发者必须使用他所能使用的工具和技巧来提高代码的质量,

【译】《C# 小技巧 -- 编写更优雅的 C#》原书名《C# Tips -- Write Better C#》

[译]<C# 小技巧 -- 编写更优雅的 C#>原书名<C# Tips -- Write Better C#> 目录 介绍(Introduction) 第一部分:各种小技巧(Part 1: Assorted Tips) 使用 LINQ 合并 IEnumerable 序列(Merging IEnumerable Sequences with LINQ) 备注 本书封面 本书的翻译未经作者授权,仅作学习用途,转载务必保留原书及作者信息.http://dontcodetired.com/

使用AmplifyJS和JQuery编写更好更优雅的javascript事件处理代码

事件(或消息)是一种常用的软件设计模式,能够降低消息处理者和消息发布者的之间的耦合,比如J2EE里面的JMS规范.设计模式中的观察者模式(也叫发布/订阅模式),这对于javascript代码同样适用.之前写的JQuery相关博客中,详细介绍了JQuery的事件处理机制和特性,具体可以参考这个目录下的文章. JQuery事件处理其实就是使用了发布/订阅模式,包括它提供的命名空间机制.自定义事件都非常的棒,但是JQuery事件处理有一个缺陷:JQuery事件都是和DOM元素相关的,但是很多时候我们并

新书《编写可测试的JavaScript代码 》出版,感谢支持

本书介绍 JavaScript专业开发人员必须具备的一个技能是能够编写可测试的代码.不管是创建新应用程序,还是重写遗留代码,本书都将向你展示如何为客户端和服务器编写和维护可测试的JavaScript代码. 从减少代码复杂性的方法,到单元测试.代码覆盖率.调试.以及自动化,您将全面学到如何编写让你和你同事能够轻松修复和维护的JavaScript代码.测试JavaScript代码是一个复杂的过程.本书将在很大程度上帮你简化该过程. 目标读者 本书主要目标受众是那些想成为JavaScript专业开发人

优化:更优雅的异步代码?

异步问题 回调地狱 异步编程中最常见的一种问题便是回调地狱. 单次ajax请求有多个回调响应 $.ajax({ type: 'get', url: '/path/to/calldata', success: function (response) { // todo sucCallback2(response); sucCallback3(response); } }) 我们产生多个success状态下的回调函数,或者多个ajax请求同时发送,全部success状态后执行回调. 如果需要在suc

框架基础:ajax设计方案(五)--- 集成promise规范,更优雅的书写代码

距离上一篇博客书写,又过去了大概几个月了,这段时间暂时离开了这个行业,让大脑休息一下.一个人旅行,一个人休息,正好也去完成一个目标 --- 拥有自己的驾照.当然,也把自己晒的黑漆马虎的.不过这一段时间虽然在技术上没有学太多东西,但是在心态上给了自己一个沉淀的机会,感觉自己变得更加沉稳和成熟,感觉这就是自己需要找到的自己,回归自我.好了,废话不多说了,虽然技术上没有学一些新的东西,但是欠的东西还是要补回来的.正如这篇博客,前端Promise规范的实现与ajax技术的集成,当时github上一个用户

编写更好的C#代码

引言 开发人员总是喜欢就编码规范进行争论,但更重要的是如何能够在项目中自始至终地遵循编码规范,以保证项目代码的一致性.并且团队中的所有人都需要明确编码规范所起到的作用.在这篇文章中,我会介绍一些在我多年的从业过程中所学习和总结的一些较好的实践. 举例为先 我们先来看一个 FizzBuzz 示例.FizzBuzz 要求编写一个程序,遍历从 1 到 100 的数字.其中如果某数字是 3 的倍数,则程序输出 “Fizz”.如果某数字是 5 的倍数,则输出 “Buzz”.如果某数字即是 3 的倍数也是