Javascript中的异步编程规范Promises/A详细介绍


Posted in Javascript onJune 06, 2014

Javascript里异步编程逐渐被大家接受,先前大家一般通过回调嵌套,setTimeout、setInterval等方式实现,代码看起来非常不直观,不看整个代码逻辑很难快速理解。Javascript里异步函数大概有I/O函数(Ajax、postMessage、img load、script load等)、计时函数(setTimeout、setInterval)等。

这些我们都很熟悉,在复杂的应用中往往会嵌套多层,甚至以为某些步骤未完成而导致程序异常,最简单的例子:比如你往DOM中注入节点,你必须等待节点注入后在操作这个节点,当大量节点注入的时候,时间往往很难把握。如果我们得代码依赖第三方api的数据。我们无法获悉一个API响应的延迟时间,应用程序的其他部分可能会被阻塞,直到它返回结果。Promises对这个问题提供了一个更好的解决方案,它是非阻塞的,并且与代码完全解耦 。

那么,我看看Javascript里异步编程,首先推荐大家看看相对来说比较流行的Promises/A规范。

Promises/A规范

注:为了便于理解,描述可能和Promises/A规范有所出入;

CommonJS之Promises/A规范,通过规范API接口来简化异步编程,使我们的异步逻辑代码更易理解。
遵循Promises/A规范的实现我们称之为Promise对象,Promise对象有且仅有三种状态:unfulfilled(未完成)、fulfilled(已完成)、failed(失败/拒绝);初始创建的时候是unfulfilled(未完成)状态,状态只可以从unfulfilled(未完成)变成fulfilled(已完成),或者unfulfilled(未完成)变成failed(失败/拒绝)。状态一旦变成fulfilled(已完成)或者failed(失败/拒绝),状态就不能再变了。

Promises/A规范提供了一个在程序中描述延时(或将来)概念的解决方案。主要的思想不是执行一个方法然后阻塞应用程序等待结果返回后再回调其他方法,而是返回一个Promise对象来满足未来监听。fulfilled状态和failed状态都可以被监听。Promise通过实现一个then接口来返回Promise对象来注册回调:

then(fulfilledHandler, errorHandler, progressHandler);

then接口用于监听一个Promise的不同状态。fulfilledHandler用于监听fulfilled(已完成)状态,errorHandler用于监听failed(失败/拒绝)状态,progressHandler用于监听unfulfilled(未完成)状态。Promise不强制实现unfulfilled(未完成)的事件监听(例如我们知道旧版本的jQuery(1.5,1.6)的Deferred就是一个Promise的实现,但没有实现对unfulfilled(未完成)状态的监听来回调progressHandler)。

一般认为,then接口返回的是一个新的Promise对象,而不是原来的Promise对象,这个新的新的Promise对象可以理解为是原来Promise对象的一个视图,它只包含原有Promise对象的一组方法,这些方法只能观察原有Promise对象的状态,而无法更改deferred对象的内在状态。这样可以避免多个调用者之间的冲突,多个调用者可以通过改变新的Promise对象状态而不影响别的调用者。

另外,Promise提供了resolve(实现状态由未完成到已完成)和reject(实现状态由未完成到拒绝或失败)两个接口实现状态的转变。

发一张图片帮助理解一下:

Javascript中的异步编程规范Promises/A详细介绍

有了Promise,就可以以同步的思维去编写异步的逻辑了。在异步函数里,不能使用try/catch捕获异常,也不能抛出异常。有了Promise,我们可以直接显式定义errorHandler,相当于捕获异常。

以下是几个遵循Promises/A规范的类库,when,q,rsvp.js,jQuery.Deferred等等。

Javascript 相关文章推荐
javascript 基础篇3 类,回调函数,内置对象,事件处理
Mar 14 Javascript
在Iframe中获取父窗口中表单的值(示例代码)
Nov 22 Javascript
js阻止默认事件与js阻止事件冒泡示例分享 js阻止冒泡事件
Jan 27 Javascript
JS倒计时代码汇总
Nov 25 Javascript
jQuery仿gmail实现fixed布局的方法
May 27 Javascript
jQuery编写网页版2048小游戏
Jan 06 Javascript
js实现兼容PC端和移动端滑块拖动选择数字效果
Feb 16 Javascript
JS实现带动画的回到顶部效果
Dec 28 Javascript
Angular使用cli生成自定义文件、组件的方法
Sep 04 Javascript
如何使用VuePress搭建一个类型element ui文档
Feb 14 Javascript
vue+elementUI动态生成面包屑导航教程
Nov 04 Javascript
Vue修改项目启动端口号方法
Nov 07 Javascript
AMD异步模块定义介绍和Require.js中使用jQuery及jQuery插件的方法
Jun 06 #Javascript
jQuery插件开发详细教程
Jun 06 #Javascript
手写的一个兼容各种浏览器的javascript getStyle函数(获取元素的样式)
Jun 06 #Javascript
jquery进行数组遍历如何跳出当前的each循环
Jun 05 #Javascript
js检验密码强度(低中高)附图
Jun 05 #Javascript
原生js编写设为首页兼容ie、火狐和谷歌
Jun 05 #Javascript
js如何判断用户是否是用微信浏览器
Jun 05 #Javascript
You might like
一个图形显示IP的PHP程序代码
2007/10/19 PHP
PHP 页面编码声明方法详解(header或meta)
2010/03/12 PHP
smarty基础之拼接字符串的详解
2013/06/18 PHP
Linux服务器下PHPMailer发送邮件失败的问题解决
2017/03/04 PHP
PHP编程获取各个时间段具体时间的方法
2017/05/26 PHP
django中的ajax组件教程详解
2018/10/18 PHP
php版本CKEditor 4和CKFinder安装及配置方法图文教程
2019/06/05 PHP
laravel 实现划分admin和home 模块分组
2019/10/15 PHP
电子商务网站上的常用的js放大镜效果
2011/12/08 Javascript
学习JavaScript设计模式之责任链模式
2016/01/18 Javascript
javascript和jquery实现用户登录验证
2016/05/04 Javascript
jQuery通用的全局遍历方法$.each()用法实例
2016/07/04 Javascript
微信小程序 SocketIO 实例讲解
2016/10/13 Javascript
使用bootstrap插件实现模态框效果
2017/05/10 Javascript
jQuery 控制文本框自动缩小字体填充
2017/06/16 jQuery
基于vue开发的在线付费课程应用过程
2018/01/25 Javascript
vue中Axios的封装与API接口的管理详解
2018/08/09 Javascript
node-red File读取好保存实例讲解
2019/09/11 Javascript
Python采用raw_input读取输入值的方法
2014/08/18 Python
python中的hashlib和base64加密模块使用实例
2014/09/02 Python
python中子类调用父类函数的方法示例
2017/08/18 Python
Python实现基于二叉树存储结构的堆排序算法示例
2017/12/08 Python
Python学习小技巧总结
2018/06/10 Python
python tkinter界面居中显示的方法
2018/10/11 Python
Python异步操作MySQL示例【使用aiomysql】
2019/05/16 Python
python SQLAlchemy的Mapping与Declarative详解
2019/07/04 Python
Python面向对象之私有属性和私有方法应用案例分析
2019/12/31 Python
使用python matplotlib 画图导入到word中如何保证分辨率
2020/04/16 Python
Oakley官网:运动太阳镜、雪镜和服装
2016/09/30 全球购物
怎么写自荐书范文
2014/02/12 职场文书
中级会计大学生职业生涯规划书
2014/09/16 职场文书
假释思想汇报范文
2014/10/11 职场文书
市场营销计划书范文
2015/01/16 职场文书
2016拓展训练心得体会范文
2016/01/12 职场文书
详解Laravel制作API接口
2021/05/31 PHP
MySQL库表名大小写的选择
2021/06/05 MySQL