Promise
Promise 就是一個(gè)對(duì)象,用來(lái)傳遞異步操作的消息每强。有了 Promise 對(duì)象始腾,就可以將異步操作以同步操作的流程表達(dá)出來(lái)。
1. Promise特點(diǎn)
- 承諾將來(lái)會(huì)執(zhí)行
- 防止回調(diào)地獄 - Callback Hell
- 可以進(jìn)行then的鏈?zhǔn)綀?zhí)行
- 區(qū)分?jǐn)?shù)據(jù)請(qǐng)求和數(shù)據(jù)處理
- 三種狀態(tài)
- pending:等待中空执,或者進(jìn)行中浪箭,表示還沒(méi)有得到結(jié)果
- resolved(fullfilled):已經(jīng)完成,表示得到了我們想要的結(jié)果辨绊,可以繼續(xù)往下執(zhí)行
- rejected:也表示得到結(jié)果奶栖,但是由于結(jié)果并非我們所愿,因此拒絕執(zhí)行
- 調(diào)用時(shí)會(huì)被傳遞兩個(gè)參數(shù):
resolve
和reject
函數(shù) - 具備
then()
方法门坷,對(duì)于then()
方法有以下簡(jiǎn)單的要求:- 接收完成態(tài)驼抹、錯(cuò)誤態(tài)的回調(diào)方法
- 可選地支持progress事件回調(diào)作為第三個(gè)方法
- 只接受function對(duì)象
- 返回Promise對(duì)象,以實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用
2. 如何創(chuàng)建AJAX
一個(gè)Ajax建立要了解以下幾點(diǎn):
- XMLHttpRequest對(duì)象的工作流程
- 兼容性處理
- 事件的觸發(fā)條件
- 事件的觸發(fā)順序
步驟:
- 創(chuàng)建
XMLHttpRequest
對(duì)象拜鹤,也就是創(chuàng)建一個(gè)異步調(diào)用對(duì)象框冀。 - 創(chuàng)建一個(gè)新的HTTP請(qǐng)求,并指定該HTTP請(qǐng)求的方法敏簿、URL及驗(yàn)證信息明也。
- 設(shè)置響應(yīng)HTTP請(qǐng)求狀態(tài)變化的函數(shù)。
- 發(fā)送HTTP請(qǐng)求惯裕。
- 獲取異步調(diào)用返回的數(shù)據(jù)温数。
- 使用JavaScript和DOM實(shí)現(xiàn)局部刷新。
3. 利用Promise知識(shí)蜻势,用原生JS封裝AJAX
var url = '/請(qǐng)求的路徑';
var params = {
id: 'id=123',
limit: 'limit=10'
};
// 封裝一個(gè)get請(qǐng)求的方法
function getJSON(url) {
return new Promise(function (resolve, reject) {
var XHR = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP');
XHR.onreadystatechange = function () {
//readyState屬性表示請(qǐng)求/響應(yīng)過(guò)程的當(dāng)前活動(dòng)階段撑刺。
if (XHR.readyState == 4) {
if ((XHR.status >= 200 && XHR.status < 300) || XHR.status == 304) {
try {
//獲取數(shù)據(jù)
var response = JSON.parse(XHR.responseText);
resolve(response);
} catch (e) {
reject(e);
}
} else {
reject(new Error("Request was unsuccessful: " + XHR.statusText));
}
}
}
XHR.open('GET', url + '?' + params.join('&'), true);
XHR.send(null);
})
}
getJSON(url).then(resp => console.log(resp));
readyState
0 - 代表未初始化。 還沒(méi)有調(diào)用 open 方法
1 - 代表正在加載握玛。 open 方法已被調(diào)用够傍,但 send 方法還沒(méi)有被調(diào)用
2 - 代表已加載完畢。send 已被調(diào)用挠铲。請(qǐng)求已經(jīng)開(kāi)始
3 - 代表正在與服務(wù)器交互中冕屯。服務(wù)器正在解析響應(yīng)內(nèi)容
4 - 代表完成。響應(yīng)發(fā)送完畢
readyState的值等于3拂苹,就是“流”(streaming)安聘,它是提升數(shù)據(jù)性能的強(qiáng)大工具。
4. Promise 語(yǔ)法
代碼以實(shí)現(xiàn)異步操作img為例
4.1 ES5 異步Callback實(shí)現(xiàn)
function loadImg(src, callback, fail) {
var img = document.createElement('img')
img.onload = function () {
callback(img)
}
img.onerror = function () {
fail()
}
img.src = src
}
var src = 'https://img.mukewang.com/5be2bcb30001a46709360316.jpg'
loadImg(src, function (img) {
console.log(img.width)
}, function () {
console.log('failed')
})
4.2 Promise實(shí)現(xiàn)
function loadImg(src) {
const promise = new Promise(function (resolve, resolve) {
var img = document.createElement('img')
img.onload = function () {
resolve(img)
}
img.onerror = function () {
reject()
}
img.src = src
})
return promise
}
var src = 'https://img.mukewang.com/5be2bcb30001a46709360316.jpg'
var result = loadImg(src)
result.then(function (img) {
console.log(img.width)
}, function () {
console.log('failed')
})
result.then(function (img) {
console.log(img.height)
})
優(yōu)點(diǎn):便于集成、擴(kuò)展
注意:
- new Promise 實(shí)例浴韭,必須要 return
- new Promise 時(shí)要傳入函數(shù)丘喻,函數(shù)有 resolve reject 兩個(gè)參數(shù)
- 成功時(shí)執(zhí)行 resolve() 失敗時(shí)執(zhí)行 reject()
4.3 重要語(yǔ)法
Promise.all接收一個(gè)Promise對(duì)象組成的數(shù)組作為參數(shù),當(dāng)這個(gè)數(shù)組所有的Promise對(duì)象狀態(tài)都變成resolved或者rejected的時(shí)候念颈,它才會(huì)去調(diào)用then方法泉粉。
Promise.race與Promise.all相似的是,Promise.race都是以一個(gè)Promise對(duì)象組成的數(shù)組作為參數(shù)舍肠,不同的是搀继,只要當(dāng)數(shù)組中的其中一個(gè)Promsie狀態(tài)變成resolved或者rejected時(shí)窘面,就可以調(diào)用.then方法了翠语。
-
如何有效的將ajax的數(shù)據(jù)請(qǐng)求和數(shù)據(jù)處理分別放在不同的模塊中進(jìn)行管理
- 將所有的數(shù)據(jù)請(qǐng)求這個(gè)動(dòng)作放在同一個(gè)模塊中統(tǒng)一管理
define(function(require) { var API = require('API'); // 因?yàn)閖Query中的get方法也是通過(guò)Promise進(jìn)行了封裝,最終返回的是一個(gè)Promise對(duì)象财边,因此這樣我們就可以將數(shù)據(jù)請(qǐng)求與數(shù)據(jù)處理放在不同的模塊肌括,即使用一個(gè)統(tǒng)一的模塊來(lái)管理所有的數(shù)據(jù)請(qǐng)求 // 獲取當(dāng)天的信息 getDayInfo = function() { return $.get(API.dayInfo); } // 獲取type信息 getTypeInfo = function() { return $.get(API.typeInfo); }; return { getDayInfo: getDayInfo, getTypeInfo: getTypeInfo } });
可以增加過(guò)濾處理
- 拿到數(shù)據(jù)并處理數(shù)據(jù)
// components/calendar.js define(function(require) { var request = require('request'); // 拿到數(shù)據(jù)之后,需要處理的組件酣难,可以根據(jù)數(shù)據(jù)渲染出需求想要的樣式 request.getTypeInfo() .then(function(resp) { // 拿到數(shù)據(jù)谍夭,并執(zhí)行處理操作 console.log(resp); }) // 這樣,我們就把請(qǐng)求數(shù)據(jù)憨募,與處理數(shù)據(jù)分離開(kāi)來(lái)紧索,維護(hù)起來(lái)就更加方便了,代碼結(jié)構(gòu)也足夠清晰 })