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 相关文章推荐
myeclipse安装jQuery插件的方法
Mar 29 Javascript
ExtJS4中的requires使用方法示例介绍
Dec 03 Javascript
利用jQuery简单实现产品展示图片左右滚动功能(示例代码)
Jan 02 Javascript
jQuery使用after()方法在元素后面添加多项内容的方法
Mar 26 Javascript
window.onload与$(document).ready()的区别分析
May 30 Javascript
jquery实现不包含当前项的选择器实例
Jun 25 Javascript
jQuery带时间的日期控件代码分享
Aug 26 Javascript
谈谈jQuery之Deferred源码剖析
Dec 19 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(二)
May 11 Javascript
浅谈struts1 &amp; jquery form 文件异步上传
May 25 jQuery
webpack构建react多页面应用详解
Sep 15 Javascript
详解iview的checkbox多选框全选时校验问题
Jun 10 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的mkdir()函数创建文件夹比较安全的权限设置方法
2014/07/28 PHP
php的ZipArchive类用法实例
2014/10/20 PHP
一张表搞清楚php is_null、empty、isset的区别
2015/07/07 PHP
crontab无法执行php的解决方法
2016/01/25 PHP
PHPCMS V9 添加二级导航的思路详解
2016/10/20 PHP
JavaScript性能优化 创建文档碎片(document.createDocumentFragment)
2010/07/13 Javascript
jquery在项目中做复选框时遇到的一些问题笔记
2013/11/17 Javascript
javascript页面加载完执行事件代码
2014/02/11 Javascript
使用jQuery将多条数据插入模态框的实现代码
2014/10/08 Javascript
jQuery中width()方法用法实例
2014/12/24 Javascript
移动端js图片查看器
2016/11/17 Javascript
Vue2.0 从零开始_环境搭建操作步骤
2017/06/14 Javascript
利用pm2部署多个node.js项目的配置教程
2017/10/22 Javascript
详解Angular Karma测试的持续集成实践
2019/11/15 Javascript
基于js实现的图片拖拽排序源码实例
2020/11/04 Javascript
python 解析html之BeautifulSoup
2009/07/07 Python
python从sqlite读取并显示数据的方法
2015/05/08 Python
Python实现包含min函数的栈
2016/04/29 Python
python opencv检测目标颜色的实例讲解
2018/04/02 Python
Numpy数组array和矩阵matrix转换方法
2019/08/05 Python
ubuntu上安装python的实例方法
2019/09/30 Python
python多继承(钻石继承)问题和解决方法简单示例
2019/10/21 Python
在django中自定义字段Field详解
2019/12/03 Python
keras tensorflow 实现在python下多进程运行
2020/02/06 Python
Roxy美国官网:澳大利亚冲浪、滑雪健身品牌
2016/07/30 全球购物
俄罗斯花园种植材料批发和零售网上商店:Беккер
2019/07/22 全球购物
美国办公用品折扣网站:Shoplet.com
2019/11/24 全球购物
华为c/c++笔试题
2016/01/25 面试题
当文件系统受到破坏时,如何检查和修复系统?
2012/03/09 面试题
校园自助餐厅的创业计划书
2013/12/26 职场文书
读群众路线心得体会
2014/03/07 职场文书
个人公开承诺书
2014/03/28 职场文书
师德师风承诺书
2014/05/23 职场文书
党员服务承诺书
2014/05/28 职场文书
作弊检讨书范文
2015/05/06 职场文书
SpringBoot前端后端分离之Nginx服务器下载安装过程
2022/08/14 Servers