下面小編就為大家?guī)硪黄猨avascript Promise簡單學習使用方法小結。小編覺得挺不錯的,現在分享給大家,也給大家做個參考。
解決回調函數嵌套太深,并行邏輯必須串行執(zhí)行,一個Promise代表一個異步操作的最終結果,跟Promise交互的主要方式是通過他的then()方法來注冊回調函數,去接收Promise的最終結果值
Promise相關的協(xié)議有PromiseA和PromiseA+
定義一個類Promise
定義屬性隊列queue,初始化空數組[]
定義屬性值value,初始化null
定義屬性狀態(tài)status,初始化“pending”(默認值)
定義成員方法getQueue(),返回屬性queue
定義成員方法getStatus(),返回屬性status
定義成員方法setStatus(),設置狀態(tài),傳遞參數:status,value
判斷status為fulfilled或者rejected,
設置status屬性this.status=status
設置value屬性this.value=value || null ,如果不傳value就是null
定義凍結變量freezeObject
定義成員方法isFulfilled(),判斷當前狀態(tài)是否是(完成)
定義成員方法isRejected(),判斷當前狀態(tài)是否是(失?。?/P>
定義成員方法isPending(),判斷當前狀態(tài)師傅是(等待)
定義成員方法then(),傳遞參數:onFulfilled成功的回調,onRejected失敗的回調
定義對象handler對象,屬性fulfilled,rejected兩個回調函數
定義handler對象的deferred屬性,Deferred對象
判斷當前狀態(tài)是否等待,如果是等待 把handler對象塞入queue隊列數組
如果不是等待狀態(tài),調用Utils對象的procedure()方法,參數:status,
返回 handler.deferred.promise對象
定義一個類Deferred
定義屬性promise,初始化Promise對象
定義成員方法resolve(),傳遞參數:result結果
判斷Promise對象的狀態(tài)是 等待,直接返回
調用Promise對象的getQueue()方法,獲取queue數組
循環(huán)數組
//todo調用工具類Utils. procedure()方法,參數:“fulfilled”,元素,err信息
調用Promise對象的setStatus()方法,設置狀態(tài),參數:'fulfilled',result
定義成員方法reject,傳遞參數:err錯誤信息
判斷Promise對象的狀態(tài)是 等待,直接返回
調用Promise對象的getQueue()方法,獲取queue數組
循環(huán)數組
//todo,調用工具類Utils. procedure()方法,參數:“rejected”,元素,err信息
調用Promise對象的setStatus()方法,設置狀態(tài),參數:'fulfilled',result
定義工具類Utils,使用匿名函數立即執(zhí)行,得到一個對象
返回對象,對象中有一個方法procedure()
定義procedure()方法,傳遞參數:type狀態(tài)類型,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的狀態(tài)是不可逆的
} 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狀態(tài)后添加回調
utils.procedure(this.status, handler, this.value);
} else {
this.queue.push(handler);//then may be called multiple times on the same promise;規(guī)范2.2.6
}
return handler.deferred.promise;//then must return a promise;規(guī)范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+規(guī)范,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簡單學習使用方法小結就是小編分享給大家的全部內容了,希望能給大家一個參考