简单实现异步编程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 相关文章推荐
js简易namespace管理器 实例代码
Jun 21 Javascript
易操作的jQuery表单提示插件
Dec 01 Javascript
浅析JS操作DOM的一些常用方法
May 13 Javascript
用js动态添加html元素,以及属性的简单实例
Jul 19 Javascript
对Js OOP编程 创建对象的一些全面理解
Jul 26 Javascript
Angular.js实现注册系统的实例详解
Dec 18 Javascript
Webpack中css-loader和less-loader的使用教程
Apr 27 Javascript
vue富文本编辑器组件vue-quill-edit使用教程
Sep 21 Javascript
jQuery选择器之层次选择器用法实例分析
Feb 19 jQuery
Vue CLI 2.x搭建vue(目录最全分析)
Feb 27 Javascript
JS字符串补全方法padStart()和padEnd()
May 27 Javascript
什么是SOLID
Mar 24 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
Terran魔法科技
2020/03/14 星际争霸
收集的二十一个实用便利的PHP函数代码
2010/04/22 PHP
Linux下手动编译安装PHP扩展的例子分享
2014/07/15 PHP
Yii框架登录流程分析
2014/12/03 PHP
php序列化函数serialize() 和 unserialize() 与原生函数对比
2015/05/08 PHP
php实现文本数据导入SQL SERVER
2015/05/17 PHP
PHP aes (ecb)解密后乱码问题
2015/06/22 PHP
PHP面向对象程序设计(OOP)之方法重写(override)操作示例
2018/12/21 PHP
PHP树形结构tree类用法示例
2019/02/01 PHP
jQuery 绑定事件到动态创建的元素上的方法实例
2013/08/18 Javascript
jQuery结合ajax实现动态加载文本内容
2015/05/19 Javascript
基于javascript实现简单的抽奖系统
2020/04/15 Javascript
jQuery制作全屏宽度固定高度轮播图(实例讲解)
2017/07/08 jQuery
如何将 jQuery 从你的 Bootstrap 项目中移除(取而代之使用Vue.js)
2017/07/17 jQuery
vue组件通信传值操作示例
2019/01/08 Javascript
微信小程序自定义组件传值 页面和组件相互传数据操作示例
2019/05/05 Javascript
vue滚动tab跟随切换效果
2020/06/29 Javascript
vuex 实现getter值赋值给vue组件里的data示例
2019/11/05 Javascript
python实现电子词典
2020/04/23 Python
python生成验证码图片代码分享
2016/01/28 Python
python 连接sqlite及简单操作
2017/06/30 Python
对numpy中array和asarray的区别详解
2018/04/17 Python
python如何获取apk的packagename和activity
2020/01/10 Python
tensorflow的计算图总结
2020/01/12 Python
解决Keras 中加入lambda层无法正常载入模型问题
2020/06/16 Python
python软件都是免费的吗
2020/06/18 Python
OpenCV 使用imread()函数读取图片的六种正确姿势
2020/07/09 Python
python使用ctypes库调用DLL动态链接库
2020/10/22 Python
详解HTML5 Canvas绘制不规则图形时的非零环绕原则
2016/03/21 HTML / CSS
Sperry官网:帆船鞋创始品牌
2016/09/07 全球购物
Expedia西班牙:预订酒店、机票、旅行和廉价度假套餐
2019/04/10 全球购物
eBay英国购物网站:eBay.co.uk
2019/06/19 全球购物
初中生物教学反思
2014/01/10 职场文书
Pytorch中TensorBoard及torchsummary的使用详解
2021/05/12 Python
MySQL GTID复制的具体使用
2022/05/20 MySQL
Python TypeError: ‘float‘ object is not subscriptable错误解决
2022/12/24 Python