举例详解JavaScript中Promise的使用


Posted in Javascript onJune 24, 2015

摘录 ? Parse JavaScript SDK现在提供了支持大多数异步方法的兼容jquery的Promises模式,那么这意味着什么呢,读完下文你就了解了。

“Promises” 代表着在javascript程序里下一个伟大的范式,但是理解他们为什么如此伟大不是件简单的事。它的核心就是一个promise代表一个任务结果,这个任务有可能完成有可能没完成。Promise模式唯一需要的一个接口是调用then方法,它可以用来注册当promise完成或者失败时调用的回调函数,这在CommonJS Promises/A proposal.大体讲到了。比如,我想保存一个Prase.Object对象,这是个异步操作,在旧的回调范式中,你的代码可能这样写:
 

object.save({ key: value }, {
 success:function(object) {
  // the object was saved.
 },
 error:function(object, error) {
  // saving the object failed.
 }
});
在新的Promise范式中,同样的代码你可以这样写:
 
object.save({ key: value }).then(
 function(object) {
  // the object was saved.
 },
 function(error) {
  // saving the object failed.
 });

没有多大的区别?那么有啥大不了的地方呢?好吧,promises的真正强大之处在于多重的链接,当调用promise.then(func)时返回一个新的promise,它不会执行直到上一个完成。但是这里有一种特殊的情况,如果我的回调通过then返回一个新的promise,那么通过then返回的promise将不会执行,直到回调执行完成。详细细节请参考 Promises/A+,这是个复杂的规则,通过例子我们能更清楚的认识下.

假设你写了段登陆的代码,查找对象然后更新它。在旧的回调范式中,你可以使用金字塔式的代码完成:
 

Parse.User.logIn("user","pass", {
 success:function(user) {
  query.find({
   success:function(results) {
    results[0].save({ key: value }, {
     success:function(result) {
      // the object was saved.
     }
    });
   }
  });
 }
});

这看起来已经很可笑,更可笑的是甚至没有任何错误处理。但是promise链式的结构,使代码看起来更舒服了:
 

Parse.User.logIn("user","pass").then(function(user) {
 returnquery.find();
}).then(function(results) {
 returnresults[0].save({ key: value });
}).then(function(result) {
 // the object was saved.
});

哇!好多啦!

错误处理

上面的代码简单期间没有添加错误处理,但是添加了后你会发现在旧的回调代码中一团糟:
 

Parse.User.logIn("user","pass", {
 success:function(user) {
  query.find({
   success:function(results) {
    results[0].save({ key: value }, {
     success:function(result) {
      // the object was saved.
     },
     error:function(result, error) {
      // An error occurred.
     }
    });
   },
   error:function(error) {
    // An error occurred.
   }
  });
 },
 error:function(user, error) {
  // An error occurred.
 }
});

由于promises知道处理是否完成,它可以传递错误,不执行任何回调直到遇到错误。比如,上面的代码可以简写为:
 

Parse.User.logIn("user","pass").then(function(user) {
 returnquery.find();
}).then(function(results) {
 returnresults[0].save({ key: value });
}).then(function(result) {
 // the object was saved.
},function(error) {
 // there was some error.
});

通常,开发者认为一个异步的promise失败等同于抛出一个异常。事实上,如果一个回调抛出一个错误,promise将返回失败信息。把错误传递到下一个可用的错误处理器等同于抛出一次异常直到捕获处理。

jQuery, Backbone, 和 Parse

有很多实现了promises的库供开发者可用。 像jQuery的 Deferred, 微软的 WinJS.Promise, when.js, q, 和dojo.Deferred.

然而,有个有趣的地方需要了解。 你可以在这里读到 long and fascinating jQuery pull request discussion, jQuery的实现没有完全按照Promises/A的规则来,很多地方用了其他实现方式,实验时,我发现只有一个地方不太一样。如果一个错误处理器返回一些其他的信息,而不单纯返回一个promise,大多数实现会考虑处理这个错误,不做错误传递。然而,jquery不认为在此处处理这个错误,而是把它向前传递。虽然,来自不同系统的promise应该能无缝的混合使用,但是你还是应当注意些。一个潜在的问题是会在错误处理器中返回promises(替换原始数值),因为它们会被同等对待。
 

doFailingAsync().then(function() {
 // doFailingAsync doesn't succeed.
},function(error) {
 // Try to handle the error.
 return"It's all good.";
}).then(function(result) {
 // Non-jQuery implementations will reach this with result === "It's all good.".
},function(error) {
 // jQuery will reach this with error === "It's all good.".
});

 
在 Backbone 0.9.10最新版本中,异步方法现在返回一个 jqXHR,这是jquery promise的一种类型。Parse JavaScript SDK的一个目标是尽可能的和Backbone兼容,我们不能返回一个jqXHR,因为它在 Cloud Code上不能很好地工作,因此,我们不都添加一个 Parse.Promise类,它遵照jQuery Deferred的标准。 Parse JavaScript SDK最新版本已经更新了所有的异步方法来支持这些新的对象,旧的回调方法仍然可用。但是基于上面列出的例子,我相信你更喜欢新的方式。所以试试promises吧!

Javascript 相关文章推荐
鼠标移到div,浮层显示明细,弹出层与div的上边距左边距重合(示例代码)
Dec 14 Javascript
JS判断客户端是手机还是PC的2个代码
Apr 12 Javascript
js 采用delete实现继承示例代码
May 20 Javascript
详解JavaScript正则表达式之RegExp对象
Dec 13 Javascript
Chrome浏览器的alert弹窗禁止再次弹出后恢复的方法
Dec 30 Javascript
详解AngularJS脏检查机制及$timeout的妙用
Jun 19 Javascript
JavaScript 异步调用
Oct 25 Javascript
javascript回调函数详解
Feb 06 Javascript
对Vue beforeRouteEnter 的next执行时机详解
Aug 25 Javascript
React手稿之 React-Saga的详解
Nov 12 Javascript
layui-laydate时间日历控件使用方法详解
Nov 15 Javascript
详解小程序如何改变onLoad的执行时机
Nov 01 Javascript
jQuery对JSON数据进行排序输出的方法
Jun 24 #Javascript
jQuery中$.extend()用法实例
Jun 24 #Javascript
深入理解JavaScript编程中的同步与异步机制
Jun 24 #Javascript
详解JavaScript中的客户端消息框架设计原理
Jun 24 #Javascript
jquery实现从数组移除指定的值
Jun 24 #Javascript
浅谈关于JavaScript API设计的一些建议和准则
Jun 24 #Javascript
详解JavaScript的策略模式编程
Jun 24 #Javascript
You might like
2019年中国咖啡业现状与发展趋势
2021/03/04 咖啡文化
php下使用以下代码连接并测试
2008/04/09 PHP
在MongoDB中模拟Auto Increment的php代码
2011/03/06 PHP
php设计模式 Observer(观察者模式)
2011/06/26 PHP
phpmyadmin安装时提示:Warning: require_once(./libraries/common.inc.php)错误解决办法
2011/08/18 PHP
php操作MongoDB类实例
2015/06/17 PHP
Zend Framework教程之Zend_Layout布局助手详解
2016/03/04 PHP
php利用云片网实现短信验证码功能的示例代码
2017/11/18 PHP
基于jQuery的的一个隔行变色,鼠标移动变色的小插件
2010/07/06 Javascript
JavaScript使用FileSystemObject对象写入文本文件内容的方法
2015/08/05 Javascript
JavaScript动态创建form表单并提交的实现方法
2015/12/10 Javascript
JS判断字符串变量是否含有某个字串的实现方法
2016/06/03 Javascript
解析微信JS-SDK配置授权,实现分享接口
2016/12/09 Javascript
BootStrop前端框架入门教程详解
2016/12/25 Javascript
原生JS和jQuery操作DOM对比总结
2017/01/19 Javascript
jQuery中.attr()和.data()的区别分析
2017/09/03 jQuery
解决vue.js 数据渲染成功仍报错的问题
2018/08/25 Javascript
Vue实现类似Spring官网图片滑动效果方法
2019/03/01 Javascript
解决在Vue中使用axios用form表单出现的问题
2019/10/30 Javascript
微信小程序关键字变色实现代码实例
2019/12/13 Javascript
vue点击按钮动态创建与删除组件功能
2019/12/29 Javascript
微信小程序实现点击导航标签滚动定位到对应位置
2020/11/19 Javascript
Python使用urllib模块的urlopen超时问题解决方法
2014/11/08 Python
Python Sql数据库增删改查操作简单封装
2016/04/18 Python
Python图形绘制操作之正弦曲线实现方法分析
2017/12/25 Python
浅谈tensorflow1.0 池化层(pooling)和全连接层(dense)
2018/04/27 Python
Django项目uwsgi+Nginx保姆级部署教程实现
2020/04/19 Python
Matlab使用Plot函数实现数据动态显示方法总结
2021/02/25 Python
详解HTML5中CSS外观属性
2020/09/10 HTML / CSS
英国高端食品和葡萄酒超市:Waitrose
2016/08/23 全球购物
什么是View State?
2013/01/27 面试题
J2EE是技术还是平台还是框架
2016/08/14 面试题
2014工程部年度工作总结
2014/12/17 职场文书
服务员岗位职责
2015/02/03 职场文书
同意落户证明
2015/06/19 职场文书
使用Redis做预定库存缓存功能
2022/04/02 Redis