將已經存在的非同步請求callback轉換為同步promise
阿新 • • 發佈:2018-12-10
由於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)
參考