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 相关文章推荐
jQuery选择器的工作原理和优化分析
Jul 25 Javascript
Jquery Change与bind事件代码
Sep 29 Javascript
兼容ie、firefox的图片自动缩放的css跟js代码分享
Jan 21 Javascript
jquery使用each方法遍历json格式数据实例
May 18 Javascript
js实现对table的增加行和删除行的操作方法
Oct 13 Javascript
javascript实现获取指定精度的上传文件的大小简单实例
Oct 25 Javascript
详解照片瀑布流效果(js,jquery分别实现与知识点总结)
Jan 01 Javascript
JS小数转换为整数的方法分析
Jan 07 Javascript
jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
Mar 07 Javascript
教你快速搭建Node.Js服务器的方法教程
Mar 30 Javascript
基于daterangepicker日历插件使用参数注意的问题
Aug 10 Javascript
vue路由结构可设一层方便动态添加路由操作
Aug 31 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
php设计模式 Proxy (代理模式)
2011/06/26 PHP
作为PHP程序员应该了解MongoDB的五件事
2013/06/03 PHP
PHP实现原比例生成缩略图的方法
2016/02/03 PHP
深入解析PHP的Laravel框架中的event事件操作
2016/03/21 PHP
浅谈php调用python文件
2019/03/29 PHP
PHP中-&gt;和=&gt;的含义及使用示例解析
2020/08/06 PHP
js 图片等比例缩放代码
2010/05/13 Javascript
JavaScript判断表单中多选框checkbox选中个数的方法
2015/08/17 Javascript
jq源码解析之绑在$,jQuery上面的方法(实例讲解)
2017/10/13 jQuery
JQuery模拟实现网页中自定义鼠标右键菜单功能
2018/11/14 jQuery
解决vue移动端适配问题
2018/12/12 Javascript
antd form表单数据回显操作
2020/11/02 Javascript
通过实例解析js可枚举属性与不可枚举属性
2020/12/02 Javascript
[01:39:42]Fnatic vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
[02:04]完美世界城市挑战赛秋季赛报名开始 谁是solo路人王?
2019/10/10 DOTA
[37:45]完美世界DOTA2联赛PWL S3 LBZS vs Phoenix 第二场 12.09
2020/12/11 DOTA
python获得linux下所有挂载点(mount points)的方法
2015/04/29 Python
python自带的http模块详解
2016/11/06 Python
python 爬虫出现403禁止访问错误详解
2017/03/11 Python
Python中几种导入模块的方式总结
2017/04/27 Python
Python实现将Excel转换为json的方法示例
2017/08/05 Python
Python中scatter函数参数及用法详解
2017/11/08 Python
Python 中包/模块的 `import` 操作代码
2019/04/22 Python
基于python求两个列表的并集.交集.差集
2020/02/10 Python
Django vue前后端分离整合过程解析
2020/11/20 Python
Pycharm创建python文件自动添加日期作者等信息(步骤详解)
2021/02/03 Python
HTML最新标准HTML5总结(必看)
2016/06/13 HTML / CSS
html5简介_动力节点Java学院整理
2017/07/07 HTML / CSS
乌克兰时尚鞋子和衣服购物网站:Born2be
2018/05/24 全球购物
KARATOV珠宝在线商店:俄罗斯珠宝品牌
2019/03/13 全球购物
美国踏板车和轻便摩托车销售网站:Mega Motor Madness
2020/02/26 全球购物
杭州龙健科技笔试题.net部分笔试题
2016/01/24 面试题
给排水工程师岗位职责
2013/11/21 职场文书
英语教师自荐信
2014/05/26 职场文书
小学标准化建设汇报材料
2014/08/16 职场文书
MySQL的存储函数与存储过程的区别解析
2022/04/08 MySQL