javascript Promise简单学习使用方法小结
来源: 阅读:736 次 日期:2016-06-27 16:05:20
温馨提示: 小编为您整理了“javascript Promise简单学习使用方法小结”,方便广大网友查阅!

下面小编就为大家带来一篇javascript Promise简单学习使用方法小结。小编觉得挺不错的,现在分享给大家,也给大家做个参考。

解决回调函数嵌套太深,并行逻辑必须串行执行,一个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简单学习使用方法小结就是小编分享给大家的全部内容了,希望能给大家一个参考

更多信息请查看网络编程
由于各方面情况的不断调整与变化, 提供的所有考试信息和咨询回复仅供参考,敬请考生以权威部门公布的正式信息和咨询为准!

2025国考·省考课程试听报名

  • 报班类型
  • 姓名
  • 手机号
  • 验证码
关于我们 | 联系我们 | 人才招聘 | 网站声明 | 网站帮助 | 非正式的简要咨询 | 简要咨询须知 | 加入群交流 | 手机站点 | 投诉建议
工业和信息化部备案号:滇ICP备2023014141号-1 云南省教育厅备案号:云教ICP备0901021 滇公网安备53010202001879号 人力资源服务许可证:(云)人服证字(2023)第0102001523号
云南网警备案专用图标
联系电话:0871-65317125(9:00—18:00) 获取招聘考试信息及咨询关注公众号:
咨询QQ:526150442(9:00—18:00)版权所有:
云南网警报警专用图标
Baidu
map