由於js是單線程執行,為防止阻塞,會有很多異步回調函數callback,嵌套層次多了,可讀性就差了很多。隨着社區的發展,出現了promise。我們來將一些常見的回調函數做修改,變成promise的鏈式調用,簡潔,清晰明了。
先理解一點點概念。
每個promise都有三個狀態。pending、Fulfilled、Rejected。最初為pending,狀態一但改變為Fulfilled、Rejected中的一種,即成永遠,不再改變。
pending: 等待狀態。
Fulfilled: 表示成功完成。
Rejected: 表示被拒絕,失敗。
原生的ajax請求
/**
* 原生請求
*/
function nativeRequest(url) {
var xhr = new XMLHttpRequest()
// 這里我建議的書寫順序是: onreadystatechange -> open -> send
// 這樣,onreadystatechange 可以獲取 readyState 的狀態 1 2 3 4
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) { // 請求已完成,且響應已就緒
if (xhr.status === 200) {
// TODO: 處理返回正常的數據 xhr.responseText
} else {
// TODO: 處理返回非正常的數據
}
}
}
xhr.open('GET', url, true)
xhr.send(null)
}
promise 風格的請求
/**
* promisify request
* 返回promise對象
*/
function promiseRequest(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.responseText)
} else {
reject(xhr.responseText)
}
}
}
xhr.open('GET', xhr, true)
xhr.send(null)
}).catch(err => {
console.log(err)
})
}
jquery中的ajax請求
這里只使用ajax請求中的get請求,使用常見的幾個參數。
/**
* ajax get請求
*/
function ajaxResponse(url) {
$.ajax({
url: url,
type: 'GET',
success: res => {
console.log(res)
},
error: err => {
console.log(err)
}
})
}
轉換為promise風格
/**
* promise風格的ajax get請求
* 返回promise對象
* 這里同時用到了es6中的解構賦值默認值和函數參數默認值
*/
function promiseAjaxResponse(url, {
type = 'GET',
} = {}) {
return new Promise((resolve, reject) => {
$.ajax({
url,
type,
success: res => {
resolve(res)
},
error: err => {
reject(err)
}
})
})
}
node風格的callback請求
nodeGet(param, function (err, data) { })
TO:
function nodeGetAysnc(param) {
return new Promise((resolve, reject) => {
nodeGet(param, function (err, data) {
if (err !== null) return reject(err)
resolve(data)
})
})
}
DOM load事件 或者其他一次性事件
function load() {
console.log('onload - end')
}
window.onload = load
TO promise
function promiseLoad() {
return new Promise(function (resolve, reject) {
window.onload = resolve
})
}
promiseLoad().then(load)
參考
1.How do I convert an existing callback API to promises?
2.How do I promisify native XHR?
