javascript Promise简单学习使用方法小结


Posted in Javascript onMay 17, 2016

解决回调函数嵌套太深,并行逻辑必须串行执行,一个Promise代表一个异步操作的最终结果,跟Promise交互的主要方式是通过他的then()方法来注册回调函数,去接收Promise的最终结果值

Promise相关的协议有PromiseA和PromiseA+

定义一个类Promise

定义属性队列queue,初始化空数组[]

定义属性值value,初始化null

定义属性状态status,初始化“pending”(默认值)

定义成员方法getQueue(),返回属性queue

定义成员方法getStatus(),返回属性status

定义成员方法setStatus(),设置状态,传递参数:status,value

判断status为fulfilled或者rejected,

设置status属性this.status=status

设置value属性this.value=value || null ,如果不传value就是null

定义冻结变量freezeObject

定义成员方法isFulfilled(),判断当前状态是否是(完成)

定义成员方法isRejected(),判断当前状态是否是(失败)

定义成员方法isPending(),判断当前状态师傅是(等待)

定义成员方法then(),传递参数:onFulfilled成功的回调,onRejected失败的回调

定义对象handler对象,属性fulfilled,rejected两个回调函数

定义handler对象的deferred属性,Deferred对象

判断当前状态是否等待,如果是等待 把handler对象塞入queue队列数组

如果不是等待状态,调用Utils对象的procedure()方法,参数:status,

返回 handler.deferred.promise对象

定义一个类Deferred

定义属性promise,初始化Promise对象

定义成员方法resolve(),传递参数:result结果

判断Promise对象的状态是 等待,直接返回

调用Promise对象的getQueue()方法,获取queue数组

循环数组

//todo调用工具类Utils. procedure()方法,参数:“fulfilled”,元素,err信息

调用Promise对象的setStatus()方法,设置状态,参数:'fulfilled',result

定义成员方法reject,传递参数:err错误信息

判断Promise对象的状态是 等待,直接返回

调用Promise对象的getQueue()方法,获取queue数组

循环数组

//todo,调用工具类Utils. procedure()方法,参数:“rejected”,元素,err信息

调用Promise对象的setStatus()方法,设置状态,参数:'fulfilled',result

定义工具类Utils,使用匿名函数立即执行,得到一个对象
 
返回对象,对象中有一个方法procedure()

定义procedure()方法,传递参数:type状态类型,handler处理器数组,result结果

获取到处理函数func,在handler[type]

到这里我看晕了。。。
 

使用方法:

定义一个函数ajax,传递参数:url路径
 

获取Deferred对象,new出来

ajax请求数据的代码,在返回数据的回调方法中

如果成功了调用Deferred对象的resolve()方法,参数:返回的数据

如果失败了调用Deferred对象的reject()方法,参数:返回的数据

返回Deferred.promise对象

调用ajax()方法,得到promise对象,参数:url,

调用promise对象的then()方法,参数:匿名函数

调用ajax()方法,获取到promise对象,返回这个对象

形成链式调用
 

js部分:

<script>
//Promise代码部分(我选择狗带)
Promise = function() {
  this.queue = [];
  this.value = null;
  this.status = 'pending';// pending fulfilled rejected
};

Promise.prototype.getQueue = function() {
  return this.queue;
};
Promise.prototype.getStatus = function() {
  return this.status;
};
Promise.prototype.setStatus = function(s, value) {
  if (s === 'fulfilled' || s === 'rejected') {
    this.status = s;
    this.value = value || null;
    this.queue = [];
    var freezeObject = Object.freeze || function(){};
    freezeObject(this);// promise的状态是不可逆的
  } else {
    throw new Error({
      message: "doesn't support status: " + s
    });
  }
};
Promise.prototype.isFulfilled = function() {
  return this.status === 'fulfilled';
};
Promise.prototype.isRejected = function() {
  return this.status === 'rejected';
}
Promise.prototype.isPending = function() {
  return this.status === 'pending';
}
Promise.prototype.then = function(onFulfilled, onRejected) {
  var handler = {
    'fulfilled': onFulfilled,
    'rejected': onRejected
  };
  handler.deferred = new Deferred();

  if (!this.isPending()) {//这里允许先改变promise状态后添加回调
    utils.procedure(this.status, handler, this.value);
  } else {
    this.queue.push(handler);//then may be called multiple times on the same promise;规范2.2.6
  }
  return handler.deferred.promise;//then must return a promise;规范2.2.7
};

var utils = (function(){
  var makeSignaler = function(deferred, type) {
    return function(result) {
      transition(deferred, type, result);
    }
  };

  var procedure = function(type, handler, result) {
    var func = handler[type];
    var def = handler.deferred;

    if (func) {
      try {
        var newResult = func(result);
        if (newResult && typeof newResult.then === 'function') {//thenable
          // 此种写法存在闭包容易造成内存泄露,我们通过高阶函数解决
          // newResult.then(function(data) {
          //   def.resolve(data);
          // }, function(err) {
          //   def.reject(err);
          // });
          //PromiseA+规范,x代表newResult,promise代表def.promise
          //If x is a promise, adopt its state [3.4]:
          //If x is pending, promise must remain pending until x is fulfilled or rejected.
          //If/when x is fulfilled, fulfill promise with the same value.
          //If/when x is rejected, reject promise with the same reason.
          newResult.then(makeSignaler(def, 'fulfilled'), makeSignaler(def, 'rejected'));//此处的本质是利用了异步闭包
        } else {
          transition(def, type, newResult);
        }
      } catch(err) {
        transition(def, 'rejected', err);
      }
    } else {
      transition(def, type, result);
    }
  };

  var transition = function(deferred, type, result) {
    if (type === 'fulfilled') {
      deferred.resolve(result);
    } else if (type === 'rejected') {
      deferred.reject(result);
    } else if (type !== 'pending') {
      throw new Error({
        'message': "doesn't support type: " + type
      });
    }
  };

  return {
    'procedure': procedure
  }
})();

Deferred = function() {
  this.promise = new Promise();
};

Deferred.prototype.resolve = function(result) {
  if (!this.promise.isPending()) {
    return;
  }

  var queue = this.promise.getQueue();
  for (var i = 0, len = queue.length; i < len; i++) {
    utils.procedure('fulfilled', queue[i], result);
  }
  this.promise.setStatus('fulfilled', result);
};

Deferred.prototype.reject = function(err) {
  if (!this.promise.isPending()) {
    return;
  }

  var queue = this.promise.getQueue();
  for (var i = 0, len = queue.length; i < len; i++) {
    utils.procedure('rejected', queue[i], err);
  }
  this.promise.setStatus('rejected', err);
}
/*****************************上面看不懂,分割线************************************/
//测试部分
ajax = function(url) {
  var def = new Deferred();

  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) {
      if ((xhr.status >=200 && xhr.status < 300) || xhr.status === 304) {
        def.resolve(xhr.responseText)
      } else {//简化ajax,没有提供错误回调
        def.reject(new Error({
          message: xhr.status
        }));
      }
    }
  };
  xhr.open('get', url, true);
  xhr.send(null);

  return def.promise;
}

ajax('test.php?act=1').then(function(data1) {
  console.log(data1);//处理data1
  return ajax('test.php?act=2');
}).then(function(data2) {
  console.log(data2);//处理data2
  return ajax('test.php?act=3');
}, function(err) {
  console.error(err);
}).then(function(data3) {
  console.log(data3);
  alert('success');
}, function(err) {
  console.error(err);
});
</script>

php:

<?php
if($_GET['act']==1){
  echo json_encode(array("code"=>200));
}else if($_GET['act']==2){
  echo json_encode(array("code"=>300));
}else if($_GET['act']==3){
  echo json_encode(array("code"=>400));
}

javascript Promise简单学习使用方法小结

以上这篇javascript Promise简单学习使用方法小结就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript的parseInt 进制问题
May 07 Javascript
Tinymce+jQuery.Validation使用产生的BUG
Mar 29 Javascript
JS实现的一个简单的Autocomplete自动完成例子
Apr 16 Javascript
js设置document.domain实现跨域的注意点分析
May 21 Javascript
实例详解JavaScript获取链接参数的方法
Jan 01 Javascript
js小数计算小数点后显示多位小数的实现方法
May 30 Javascript
jQuery实现的自定义弹出层效果实例详解
Sep 04 Javascript
轻松理解vue的双向数据绑定问题
Oct 30 Javascript
详谈DOM简介及节点、属性、查找节点的方法
Nov 16 Javascript
Vue引用第三方datepicker插件无法监听datepicker输入框的值的解决
Jan 27 Javascript
关于vue中watch检测到不到对象属性的变化的解决方法
Feb 08 Javascript
关于JS中的作用域中的问题思考分享
Apr 06 Javascript
关于安卓手机微信浏览器中使用XMLHttpRequest 2上传图片显示字节数为0的解决办法
May 17 #Javascript
Web前端新人笔记之jquery入门心得(新手必看)
May 17 #Javascript
Angularjs中的事件广播 —全面解析$broadcast,$emit,$on
May 17 #Javascript
iScroll.js 使用方法参考
May 16 #Javascript
BootStrap的JS插件之轮播效果案例详解
May 16 #Javascript
老司机带你解读jQuery插件开发流程
May 16 #Javascript
jQuery 获取多选框的值及多选框中文的函数
May 16 #Javascript
You might like
如何开始收听短波广播
2021/03/01 无线电
PHP 分页原理分析,大家可以看看
2009/12/21 PHP
PHP新手NOTICE错误常见解决方法
2011/12/07 PHP
学习php设计模式 php实现状态模式
2015/12/07 PHP
CI框架的安全性分析
2016/05/18 PHP
PHP设计模式之适配器模式原理与用法分析
2018/04/25 PHP
PHP文件上传小程序 适合初学者学习!
2019/05/23 PHP
javascript instanceof,typeof的区别
2010/03/24 Javascript
用jquery设置按钮的disabled属性的实现代码
2010/11/28 Javascript
.net,js捕捉文本框回车键事件的小例子(兼容多浏览器)
2013/03/11 Javascript
IE8的JavaScript点击事件(onclick)不兼容的解决方法
2013/11/22 Javascript
JS实现判断滚动条滚到页面底部并执行事件的方法
2014/12/18 Javascript
详解angularJS自定义指令间的相互交互
2017/07/05 Javascript
vue.js2.0点击获取自己的属性和jquery方法
2018/02/23 jQuery
使用watch监听路由变化和watch监听对象的实例
2018/02/24 Javascript
JS中appendChild追加子节点无效的解决方法
2018/10/14 Javascript
ES6 系列之 Generator 的自动执行的方法示例
2018/10/19 Javascript
使用vue-router在Vue页面之间传递数据的方法
2019/07/15 Javascript
微信小程序实现手势滑动卡片效果
2019/08/26 Javascript
jQuery利用cookie 实现本地收藏功能(不重复无需多次命名)
2019/11/07 jQuery
对numpy的array和python中自带的list之间相互转化详解
2018/04/13 Python
Python hashlib模块用法实例分析
2018/06/12 Python
python将回车作为输入内容的实例
2018/06/23 Python
python中ASCII码和字符的转换方法
2018/07/09 Python
解决Pycharm 包已经下载,但是运行代码提示找不到模块的问题
2019/08/31 Python
Python xlrd excel文件操作代码实例
2020/03/10 Python
Tensorflow--取tensorf指定列的操作方式
2020/06/30 Python
css3媒体查询中device-width和width的区别详解
2020/03/27 HTML / CSS
科尔士百货公司官网:Kohl’s
2016/07/11 全球购物
Hotels.com台湾:饭店订房网
2017/09/06 全球购物
Tirendo比利时:在线购买轮胎
2018/10/22 全球购物
美体小铺法国官方网站:The Body Shop法国
2020/06/04 全球购物
财务工作者先进事迹材料
2014/01/17 职场文书
《小鹰学飞》教学反思
2014/04/23 职场文书
师德师风自我剖析材料
2014/09/27 职场文书
村主任“四风”问题个人对照检查材料思想汇报
2014/10/02 职场文书