函數在 javascript 中可以作為參數或作為傳回值,在異步程式設計中回調函數被大量使用,當回調函數被調用,說明滿足了某個觸發條件,有時還會包含結果,提供更多的細節。回調函數可能會出現回調地獄現象,可以利用 promise 對象解決該問題。
回調函數
小明在奶茶店點了奶茶,店員開始制作奶茶,此時“制作奶茶”與“小明等待奶茶”是一個同時進行的不同的兩個事件(任務),那麼,小明擷取店員制作成功的奶茶是從“制作奶茶”這一事件擷取的結果,是以小明才能夠完成“購買奶茶”這一事件。如果,小明在“購買奶茶”這一事件中,不想一直等待而是想去做一些其他的事情,比如購買冰淇淋。
現在,我們将這一案例抽取為一個個事件,用 javascript 函數展現出來:
目前,這些事件屬于同步任務(事件),它們被主線程由上到下依次執行,無法在同一時間内執行多個事件。你會發現,這些事件之間是各自獨立的。如何将它們有機地、有序地結合在一起是一個問題。
是以,在 javascript 中,有一種解決方式叫做異步任務(事件),利用回調函數将這些獨立的事件結合在一起。在 javascript 中,函數作為第一等公民的存在,可以将函數作為對象傳遞給方法作為實參進行調用,即回調函數。
請轉至“[js]函數作為值”一文,了解什麼函數是如何作為值,并且可以作為函數實參進行傳遞以及調用的。
回調函數的确将這些獨立事件有機地結合在一起了,但是随之而來的就是回調地獄。
現在,我們明白了回調函數的好處。再列舉一個例子,深入了解回調函數的好處在哪。若實作一個簡單的電腦,其功能有加、減、乘、除等運算,通常情況下會想到一個函數獲得兩個參數,并将運算類型作為字元串傳遞給函數參數以實作不同需求。
上述代碼,存在一個明顯的問題。如果在減法中做其他的限制條件(或增加源代碼的功能),它會影響到整個 calculate 函數本身。再者,如果我擴充 calculate 函數功能,它也會影響到函數本身。對于這種情況,我們寄希望于回調函數,通過它來解決這個問題。
現在,調用 calculate 函數時,可以在回調函數中做一些附加限制條件,它不會影響到 calculate 這個函數本體。并且,回調函數可以從 calculate 函數本體中擷取更多的細節(資訊),通過這些資訊我們又能做出更多的操作。
在回調函數中不同的排序方式可以決定最後的結果。回調函數使得程式更加靈活。
回調地獄
在上面的“小明買奶茶”案例中,回調内部再嵌套回調,其代碼形狀上看着像180°旋轉之後的金字塔,這種層層嵌套就是回調地獄。
是以,promise 可以解決回調地獄的問題。promise 是一個對象,用于表示一個異步操作的最終完成(或失敗)及其結果值。
利用 promise 解決“小明買奶茶”回調地獄:
在代碼層面,使用 promise 之後,解決了多層回調函數調用導緻的“金字塔”現象。讓我們看看實作效果:
請轉至 mdn 關于 promise 的解釋:promise - javascript | mdn