- 回調函數(callback)
setTimeout(() => { // callback 函數體 }, 1000)
ajax('XXX1', () => { // callback 函數體 ajax('XXX2', () => { // callback 函數體 ajax('XXX3', () => { // callback 函數體 }) }) })
優點:
-
簡單、容易理解
-
解決了同步的問題(只要有一個任務耗時很長,后面的任務都必須排隊等着, 會拖延整個程序的執行。)
缺點:
-
易形成回調地獄
-
不能用try...catch捕獲錯誤
-
不能return
-
不利於維護,代碼耦合高
- 事件監聽
var events = new Events(); events.addEvent('done', function(data1) { var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.apiopen.top/weatherApi?city=番禺'); xhr.send(); xhr.onreadystatechange = function() { if(this.readyState !== 4) return; if(this.status === 200) { data1 = JSON.parse(data1); var data2 = JSON.parse(this.response); console.log(data1, data2); } } }); var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.apiopen.top/weatherApi?city=廣州'); xhr.send(); xhr.onreadystatechange = function() { if(this.readyState !== 4) return; if(this.status === 200) { events.fireEvent('done', this.response); } };
優點:
1、與回調函數相比,事件監聽方式實現了代碼的解耦,將兩個回調函數分離了開來, 更方便進行代碼的管理。
2、容易理解,可以綁定多個事件,每個事件可以指定多個回調函數
缺點:
1、使用起來不方便,每次都要手動地綁定和觸發事件
-
發布/訂閱(觀察者模式)
類似於事件監聽,但是可以通過‘消息中心‘,知道現在有多少發布者,多少訂閱者;
-
Promise
promise就是為了解決callback的問題而產生的。
Promise 實現了鏈式調用,也就是說每次 then 后返回的都是一個全新 Promise, 如果我們在 then 中 return ,return 的結果會被 Promise.resolve() 包裝。
優點:
1、解決回調地獄問題
2、更好地進行錯誤捕獲
缺點:
1、無法取消promise,一旦新建它就會立即執行,無法中途取消;
2、如果不設置回調函數,promise內部拋出的錯誤,不會反應到外部;
3、當處於pending狀態時,無法得知目前進展到哪一個階段(剛剛開 始還是即將完成)
- Generator
function *fetch() { yield ajax('XXX1', () => {}) yield ajax('XXX2', () => {}) yield ajax('XXX3', () => {}) } let it = fetch() let result1 = it.next() let result2 = it.next() let result3 = it.next()
優點:
generator 方式使得異步操作很接近同步操作,十分的簡潔明了。另外,gen 執行 yield 語句時,只是將執行上下文暫時彈出,並不會銷毀,這使得上下文狀態被保存
缺點:
流程管理不方便,需要一個執行器來執行 generator 函數
-
Async/await
async、await 是異步的終極解決方案
優點:
1、最簡潔,最符合語義,最接近同步代碼,最適合處理多個 Promise 異步操作。
2、相比 generator 方式,async 方式省掉了自動執行器,減少了代碼量
缺點:
await 將異步代碼改造成同步代碼,如果多個異步操作沒有依賴性而使用 await 會導致性能上的降低。