简单实现异步编程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里使用Dom操作Xml
Jan 22 Javascript
离开当前页面前使用js判断条件提示是否要离开页面
May 02 Javascript
Javascript判断文件是否存在(客户端/服务器端)
Sep 16 Javascript
Node.js中安全调用系统命令的方法(避免注入安全漏洞)
Dec 05 Javascript
JS实现网页标题随机显示名人名言的方法
Nov 03 Javascript
AngularJS Bootstrap详细介绍及实例代码
Jul 28 Javascript
浅谈vue的踩坑路
Aug 31 Javascript
vue二级路由设置方法
Feb 09 Javascript
vue组件开发之用户无限添加自定义填写表单的方法
Aug 28 Javascript
详解Vue中使用插槽(slot)、聚类插槽
Apr 12 Javascript
解决cordova+vue 项目打包成APK应用遇到的问题
May 10 Javascript
使用webpack和rollup打包组件库的方法
Feb 25 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浮点比较大小的方法
2016/02/14 PHP
php实现文件上传及头像预览功能
2017/01/15 PHP
Laravel 框架控制器 Controller原理与用法实例分析
2020/04/14 PHP
JQuery优缺点分析说明
2010/06/09 Javascript
JavaScript经典效果集锦
2010/07/06 Javascript
JS遮罩层效果 兼容ie firefox jQuery遮罩层
2010/07/26 Javascript
网页中CDATA标记的说明
2010/09/12 Javascript
js去空格技巧分别去字符串前后、左右空格
2013/10/21 Javascript
简单的js表单验证函数
2013/10/28 Javascript
js字符串截取函数substr substring slice使用对比
2013/11/27 Javascript
Node.js(安装,启动,测试)
2014/06/09 Javascript
jquery中map函数与each函数的区别实例介绍
2014/06/23 Javascript
Nodejs异步回调的优雅处理方法
2014/09/25 NodeJs
JS往数组中添加项性能分析
2015/02/25 Javascript
JavaScript中神奇的call()方法
2015/03/12 Javascript
js获得当前系统日期时间的方法
2015/05/06 Javascript
js日期相关函数dateAdd,dateDiff,dateFormat等介绍
2016/09/24 Javascript
原生js实现简单的模态框示例
2017/09/08 Javascript
微信小程序图片右边加两行文字的代码
2020/04/23 Javascript
解决vue中使用less/sass及使用中遇到无效的问题
2020/10/24 Javascript
[03:09]2014DOTA2国际邀请赛 赛场上的美丽风景线 中国Coser也爱DOTA2
2014/07/20 DOTA
[49:30]DOTA2-DPC中国联赛正赛 Dragon vs Dynasty BO3 第二场 3月4日
2021/03/11 DOTA
用实例分析Python中method的参数传递过程
2015/04/02 Python
python3实现跳一跳点击跳跃
2018/01/08 Python
在PyCharm中三步完成PyPy解释器的配置的方法
2018/10/29 Python
Python Django框架模板渲染功能示例
2019/11/08 Python
浅谈cv2.imread()和keras.preprocessing中的image.load_img()区别
2020/06/12 Python
html5的画布canvas——画出弧线、旋转的图形实例代码+效果图
2013/06/09 HTML / CSS
太阳镜仓库,售价20美元或更少:Sunglass Warehouse
2016/09/28 全球购物
台湾母婴用品购物网站:Infant婴之房
2018/06/15 全球购物
颇特女士:NET-A-PORTER(直邮中国)
2020/07/11 全球购物
描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理
2015/03/25 面试题
自我鉴定写作要点
2014/01/17 职场文书
办公室文员岗位职责
2015/02/04 职场文书
丧事答谢词大全
2015/09/30 职场文书
台式电脑蓝牙适配器怎么安装?台式电脑蓝牙适配器安装教程
2022/04/08 数码科技