简单实现异步编程promise模式


Posted in Javascript onJuly 31, 2015

异步编程
javascript异步编程, web2.0时代比较热门的编程方式,我们平时码的时候也或多或少用到,最典型的就是异步ajax,发送异步请求,绑定回调函数,请求响应之后调用指定的回调函数,没有阻塞其他代码的执行。还有像setTimeout方法同样也是异步执行回调的方法。

如果对异步编程还不太熟悉的话,直接戳 阮一峰大牛的教程 ,这篇文章介绍了四种异步编程的方式:

  1. 回调函数
  2. 事件监听
  3. 发布/订阅
  4. promise模式

这几种方式的可维护性逐级递增,理解难度也逐级递增。这篇总结也是针对promise模式的。

promise模式
那么多中异步编程的方式,为什么选择promise, 因为前面几种方式不够灵活,用起来不够痛快,不优雅。为了降低异步编程的复杂性,所以promise。

promise的核心是有一个promise对象,这个对象有一个重要的then()方法, 它用于指定回调函数,如:

f1().then(f2);

promise模式在任何时刻都有三种状态:已完成(resolved),未完成(unfulfilled),那么then()方法就是为状态变化指定不同的回调函数,并总是返回一个promise对象,方便链式调用。

那promise模式下,返回的数据如何在各个回调函数之间传播呢,通过resolve方法,你可以将一个函数的返回值作为参数传递给另一个函数,并且将另一个函数的返回值作为参数再传递给下一个函数……像一条“链”一样无限的这么做下去。

代码实现
通过创建一个Promise构造函数来实现promise模式:

//constructor
var Promise = function() {
 this.callbacks = [];
}
Promise.prototype = {
 construct: Promise,
 resolve: function(result) {
  this.complete("resolve", result);
 },
 reject: function(result) {
  this.complete("reject", result);
 },
 complete: function(type, result) {
  while (this.callbacks[0]) {
   this.callbacks.shift()[type](result);
  }
 },
 then: function(successHandler, failedHandler) {
  this.callbacks.push({
   resolve: successHandler,
   reject: failedHandler
  });
  return this;
 }
}
// test
var promise = new Promise();
var delay1 = function() {
 setTimeout(function() {
  promise.resolve('数据1');
 }, 1000);
 return promise;
};
var callback1 = function(re) {
 re = re + '数据2';
 console.log(re);
};
delay1().then(callback1)

代码分析
我们可看到一个简单的promise对象的构造函数的结构:

简单实现异步编程promise模式

  • callbacks: 用于管理回调函数
  • resolve: 请求成功时执行的方法
  • reject:请求失败时执行的方法
  • complete: 执行回调
  • then:绑定回调函数

测试:

var promise = new Promise();
var delay1 = function() {
 setTimeout(function() {
  promise.resolve('数据1');
 }, 1000);
 return promise;
};
var callback1 = function(re) {
 re = re + '数据2';
 console.log(re);
 promise.resolve(re);
};
var callback2 = function(re) {
 console.log(re + '数据3');
};
delay1().then(callback1).then(callback2);

结果:

一秒之后输出:

简单实现异步编程promise模式

分析:

//第一步
var delay1 = function() {
 setTimeout(function() {
  promise.resolve('数据1');
 }, 1000);
 return promise;
};

这个函数通过setTimeout方法,异步传递一个数据1,并返回一个promise对象(必须)。

//第二步
var callback1 = function(re) {
 
 re = re + '数据2';
 console.log(re);
 promise.resolve(re);
};

callback1和callback2都是要通过then方法注册的回调函数,其中callback1通过resolve方法把数据往下传递。

//第三步
delay1().then(callback1).then(callback2);

delay1()方法执行完,因为返回了一个promise对象,所以可以再调用then()方法为delay1()的setTimeout异步执行操作指定回调函数, 又因为then()方法也返回的是promise对象,所以还可以再调用then方法

//第四步
setTimeout(function() {
 promise.resolve('数据1');
}, 1000);

一秒之后,当其他代码执行完成,开始执行异步代码promise.resolve('数据1');,这里调用promise的resolve()方法,指定了一个成功状态,并把数据1作为参数。

//第五步
resolve: function(result) {
 this.complete("resolve", result);
},
//第六步:循环执行回调,将上一个回调的结果传递给下一个回调
complete: function(type, result) {
 while (this.callbacks[0]) {
  this.callbacks.shift()[type](result);
 }
},

这其中比较难理解的就是第五,六步。

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
JavaScript 全面解析各种浏览器网页中的JS 执行顺序
Feb 17 Javascript
jQuery选择头像并实时显示的代码
Jun 27 Javascript
juqery 学习之三 选择器 子元素与表单
Nov 25 Javascript
js脚本分页代码分享(7种样式)
Aug 19 Javascript
JS检测页面中哪个HTML标签触发点击事件的方法
Jun 17 Javascript
AngularJS实现星星等级评分功能
Sep 24 Javascript
jQuery插件autocomplete使用详解
Feb 04 Javascript
bootstrap daterangepicker双日历时间段选择控件详解
Jun 15 Javascript
vue组件详解之使用slot分发内容
Apr 09 Javascript
vue实现商品加减计算总价的实例代码
Aug 12 Javascript
vue新建项目并配置标准路由过程解析
Dec 09 Javascript
js实现单元格拖拽效果
Feb 10 Javascript
JavaScript数据类型判定的总结笔记
Jul 31 #Javascript
jquery代码实现多选、不同分享功能
Jul 31 #Javascript
Jquery实现瀑布流布局(备有详细注释)
Jul 31 #Javascript
jquery实现仿JqueryUi可拖动的DIV实例
Jul 31 #Javascript
jQuery+css3实现文字跟随鼠标的上下抖动
Jul 31 #Javascript
JavaScript实现图片轮播的方法
Jul 31 #Javascript
基于bootstrap3和jquery的分页插件
Jul 31 #Javascript
You might like
PHP利用str_replace防注入的方法
2013/11/10 PHP
将函数的实际参数转换成数组的方法
2010/01/25 Javascript
什么是DOM(Document Object Model)文档对象模型
2012/03/05 Javascript
jquery mobile changepage的三种传参方法介绍
2013/09/13 Javascript
利用jquery写的左右轮播图特效
2014/02/12 Javascript
理解JavaScript表单的基础知识
2016/01/25 Javascript
JS组件Bootstrap实现图片轮播效果
2016/05/16 Javascript
利用Javascript实现BMI计算器
2016/08/16 Javascript
JavaScript使用正则表达式获取全部分组内容的方法示例
2017/01/17 Javascript
BootStrap中的模态框(modal,弹出层)功能示例代码
2018/11/02 Javascript
Node.js如何对SQLite的async/await封装详解
2019/02/14 Javascript
js实现盒子移动动画效果
2020/08/09 Javascript
react项目从新建到部署的实现示例
2021/02/19 Javascript
python实现查询IP地址所在地
2015/03/29 Python
Python找出list中最常出现元素的方法
2016/06/14 Python
Python2.7读取PDF文件的方法示例
2017/07/13 Python
Python使用django框架实现多人在线匿名聊天的小程序
2017/11/29 Python
python和flask中返回JSON数据的方法
2018/03/26 Python
Python中将dataframe转换为字典的实例
2018/04/13 Python
python matplotlib绘图,修改坐标轴刻度为文字的实例
2018/05/25 Python
Python 实现子类获取父类的类成员方法
2019/01/11 Python
Python实现的栈、队列、文件目录遍历操作示例
2019/05/06 Python
机器学习实战之knn算法pandas
2019/06/22 Python
python使用pip安装SciPy、SymPy、matplotlib教程
2019/11/20 Python
Python Map 函数的使用
2020/08/28 Python
社区版pycharm创建django项目的方法(pycharm的newproject左侧没有项目选项)
2020/09/23 Python
Pyqt助手安装PyQt5帮助文档过程图解
2020/11/20 Python
详解Open Folder as PyCharm Project怎么添加的方法
2020/12/29 Python
CSS3实现闪烁动画效果的方法
2015/02/09 HTML / CSS
Abe’s of Maine:自1979以来销售相机和电子产品
2016/11/21 全球购物
火箭队口号
2014/06/18 职场文书
2014国庆65周年领导讲话稿(3篇)
2014/09/21 职场文书
世界遗产的导游词
2015/02/13 职场文书
三年级作文之小小梦想
2019/12/06 职场文书
为Java项目添加Redis缓存的方法
2021/05/18 Redis
Python字符串常规操作小结
2022/04/03 Python