在 Promises 中编写更规范的 JavaScript 代码
你可能听说过周围的人谈 Promises 的未来是怎样的。 所有时尚的年轻人使用它们,但你看不到是什么让他们如此特别。 你不能只使用一个回调函数,在这篇文章中,我们将看看什么是 Promises,以及如何使用它们来编写更好的 JavaScript 。
Promises 更容易阅读
比方说,我们要抓住一些 HipsterJesus API 的数据,并将其添加到我们的页面。 这个 API 响应的数据看起来像这样:
{ "text": "<p>Lorem ipsum...</p>", "params": { "paras": 4, "type": "hipster-latin" } }
使用回调,我们会写这样的代码:
$.getJSON('http://hipsterjesus.com/api/', function(data) { $('body').append(data.text); });
如果你使用过 jQuery,那么你会知道我们正在做一个 GET 请求,并期待在 JSON 响应正文。 我们还传递一个回调函数,它的响应 JSON 并将其添加到文档中。 另一种方式来写,这是使用由返回的 Promise 对象的 getJSON 方法。 你可以直接连接一个回调到这个对象。
var promise = $.getJSON('http://hipsterjesus.com/api/'); promise.done(function(data) { $('body').append(data.text); });
像回调示例中,该附加的 API 请求的结果到该文件时,请求是成功的。 但是如果请求失败会发生什么? 我们还可以附加一个 fail 处理程序,以我们的 Promises。
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
的变量,这使得它更容易一些,告诉一下代码的作用一目了然。
$.getJSON('http://hipsterjesus.com/api/') .done(function(data) { $('body').append(data.text); }) .fail(function() { $('body').append('<p>Oh no, something went wrong!</p>'); });
jQuery 的还包括一个 always
这就是所谓的不管,如果请求成功或失败的事件处理程序。
$.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>'); });
使用 Promises 回调的顺序得到尊重。 我们保证有我们 done
所谓的先回调,那么我们 fail
的回调,最后我们 always
回调。
更好的API
比方说我们要创建一个包装对象的 HipsterJesus 的 API。 我们将添加一个方法 html()
,以返回来自 API 下来的HTML数据。 而不是这种方法需要在这就是所谓的请求时解决处理,我们只要有方法返回一个 Promise 对象。
var hipsterJesus = { html: function() { return $.getJSON('http://hipsterjesus.com/api/').then(function(data) { return data.text; }); } };
这个很酷的事情是我们可以通过我们的周围物体的 Promises,而不必担心何时或如何解决它的价值。 需要 Promises 的返回值的任何代码就可以只登记一个回调 done
。 在 then
方法允许我们修改一个 Promises 的结果,并将它传递给链中的下一个处理程序。 这意味着我们现在可以使用我们喜欢这个新的 API:
hipsterJesus.html().done(function(html) { $("body").append(html); });
直到最近 ,中 AngularJS 的杀手锏之一就是模板可以直接绑定到 Promises。 在一个角控制器,这看起来像:
$scope.hipsterIpsum = $http.get('http://hipsterjesus.com/api/');
那么它是那样简单写 {{ hipsterIpsum.text }}
在模板中。 当 Promises 解决角度会自动更新视图。 不幸的是,角队弃用此功能。 现在它可以通过调用启用 $parseProvider.unwrapPromises(true)
。 我希望角和其他框架包含此功能前进。
链接
关于 Promises 的最好的部分是可以随时修改和定义多个方法,比方说我们要一个方法添加到我们的 API,返回段的数组。
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
的方法。 因为 Promises 的回调的返回值传递给链中的下一个回调,我们可以自由地创建更改数据,因为它是通过它们体积小巧,功能的方法。 我们可以 Promises 链,因为我们希望尽可能多的时间。 让我们添加的句子的方法。
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(/. /); })); }); } };
多次调用
可能 Promises 的最显着特点是将多个 API 调用结合的能力。 当使用回调,如果你需要一次做两个 API 调用会发生什么? 你可能会写出来是这样的:
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(); });
有了 Promises,这变得容易多了:
var firstPromise = $.get("http://example.com/first"); var secondPromise = $.get("http://example.com/second"); $.when(firstPromise, secondPromise).done(function(firstData, secondData) { // do something });
在这里,我们使用 when 方法来附加一个这就是所谓的当两个请求进行处理。 结论就是这样! 希望你有一些真棒事情可以做到的 Promises 感受。
什么是你最喜欢的方式来使用它们呢? 让我知道在评论!
注:为简单起见,本文使用jQuery的延迟实现。 有jQuery的细微差异Deferred对象和Promises/A+规范 ,这是一个比较规范的标准。 欲了解更多信息,请查看Q'S 从jQuery的维基即将 。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论