zl程序教程

您现在的位置是:首页 >  前端

当前栏目

[javascript] Promise简单学习使用详解编程语言

JavaScript学习编程语言 使用 详解 简单 Promise
2023-06-13 09:20:37 时间

原文地址:http://www.cnblogs.com/dojo-lzz/p/4340897.html

 

解决回调函数嵌套太深,并行逻辑必须串行执行,一个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: "doesnt 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: "doesnt 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简单学习使用详解编程语言 

12725.html

cjavaphpxml