promise 詳解
概念:Promise是非同步程式設計的一種解決方案,比傳統的解決方案——回撥函式和事件——更合理和更強大。所謂Promise,簡單說就是一個容器,裡面儲存著某個未來才會結束的事件(通常是一個非同步操作)的結果。
直接看各種demo 拗口的文字直接丟棄掉,選擇遺忘吧
promise 出現的原因
let cb = (data) => {
console.log(data)
}
let ajax = (cb) => {
console.log('ajax ---- ')
if (typeof cb == 'function') {
cb('callback ----')
}
}
ajax(cb)
/**
* console.log
* ajax ----
* callback ----
*/
複製程式碼
1.缺點一直需要cb傳遞,如果掛在全域性物件,則會操作汙染
2.程式碼易讀性比較差
3.特別需要獲取多個非同步操作時,無法很好檢測結果完成
舉例子說明上述第三點
let num = 1;
let ajax1 = () => {
setTimeout(() => {
num++;
console.log(1000);
callbackAll();
}, 1000)
}
let ajax2 = () => {
setTimeout(() => {
num++;
console.log(1500)
callbackAll();
}, 1500)
}
let ajax3 = () => {
setTimeout(() => {
num++;
console.log(2000)
callbackAll();
}, 2000)
}
let ajaxAll = () => {
ajax1();
ajax2();
ajax3();
}
let callbackAll = () => {
if (num == 3) {
// 全部完成
console.log('全部完成~')
}
}
複製程式碼
如果用promise 方案解決 程式碼如下
let ajax1 = () => {
return new Promise((reslove, reject) => {
setTimeout(() => {
console.log(1000);
}, 1000)
})
}
let ajax2 = () => {
return new Promise((reslove, reject) => {
setTimeout(() => {
console.log(1500);
}, 1500)
})
}
let ajax3 = () => {
return new Promise((reslove, reject) => {
setTimeout(() => {
console.log(2000);
}, 2000)
})
}
Promise.all([ajax1, ajax2, ajax3]).then(function() {
console.log('全部完成~')
}).catch(function(err) {
})
/**
* 對比一下,會看到程式碼的整體的美觀度得到很大的提升
*
*/
複製程式碼
既然說到了promise all then catch 我們來分別講解一下
then 所有的promise例項 都有then 方法,來對這個promise例項 做下一步的處理,then 接受兩個方法,第一個對應resolve 第二個對應 reject
let person = () => {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(10)
}, 1000)
})
.then(function(data) {
console.log(data)
})
}
// data == 10
// 有時候會看到直接return 的資料
// promise 例項 被 resolved then方法的第一個回掉方法會被執行
複製程式碼
如果被 rejected,then方法的第二個回掉會被執行
let person = () => {
return new Promise((resolve, reject) => {
setTimeout(function() {
reject(20)
}, 1000)
})
.then(function(num) {
console.log(num + 'suc')
}, function(num) {
console.log(num + 'err')
})
}
複製程式碼
catch promise 例項 被rejected時,catch回撥函式被執行
可以參考下面的例子
new Promise((res, rej) => {
setTimeout(function() {
rej(11)
}, 500)
}).then(function() {
console.log('success')
}).catch((err) => {
console.log('err')
})
複製程式碼
all 有許多個非同步任務被同時觸發,但你只想在它們都完成之後才做出迴應---這就是Promise.all的由來。Promise.all方法傳入一個promise的陣列,然後在它們全部resolved之後再出發回撥函式
Promise.all([promise1, promise1]).then(function(data) {
// promise1 promise2 全部完成後 才會執行這裡
})
.catch(function(error) {
// promise1 promise2 出現一個 rejected 時 執行這裡
});
複製程式碼
race不是等待所有的promise被resolved或者rejected,而是隻要陣列中有一個promise被resolved或者rejected,Promise.race方法就被觸發
var promise1 = new Promise(function(resolve, reject) {
// A mock async action using setTimeout
setTimeout(function() { resolve('1111!'); }, 8000);
});
var promise2 = new Promise(function(resolve, reject) {
// A mock async action using setTimeout
setTimeout(function() { resolve('2222!'); }, 3000);
});
Promise.race([promise1, promise2]).then(function(one) {
console.log('執行結果: ', one);
}).catch(function(one, two) {
console.log('報錯資訊: ', one);
});
複製程式碼
總結:
promise 結果回撥地獄的老問題,而且在串聯操作的方面then方法的使用使我們在處理業務邏輯時更好的去維護程式碼
promise 在前端中的使用越來越多,如果你不理解,確實缺少了一大利器
接下來 編寫自己的 promise 更深層次的理解promise 的原理
如果錯誤,請指出,感謝~