面試官:你知道Callback Hell(回撥地獄)嗎?

Kev1nzh發表於2019-04-01

面試官:你知道Callback Hell(回撥地獄)嗎?

前言

這個是作者寫的面試篇章系列第一章,基本源於作者之前一個月內的面試總結,謝謝觀看。


回撥是啥?為什麼叫回撥地獄?

do('eat', (dishes) => {
    //吃完飯後再去洗盤子
    washDishes(dishes)
})
複製程式碼

上面的程式碼,大家都常常看到,包括ajax、各種模組的方法等等,他們都是回撥函式。

其實就是在執行某些操作(吃飯)後,得到特定資料(盤子),再去呼叫的一個方法(洗盤子)。

我用著挺好的,為什麼會出現回撥地獄呢?

ajax1(url, () => {
    ajax2(url, () => {
        ajax3(url, () => {
        doSomething()
        })
    })
})
複製程式碼

如果在寫業務程式碼的時候,有好幾個介面需要你使用,然鵝介面A需要介面B的回撥res引數去請求資料呢? 所以就會寫成三四個回撥函式巢狀。

這樣寫程式碼,雖然看著挺好的,但是少的還好,如果7、8個類似場景就爆炸了!

首先說下缺點

  • 程式碼耦合,一旦修改,原地爆炸。
  • 無法使用try catch,就無法排錯,也是原地爆炸。

大佬們大家一起想辦法,想著想著,就有以下幾種作者擅長的解決方案。

1. generator

const eat = function* () {
    yield 1;
    yield 2;
    return 3;
}
let do = eat();
do.next(); // { value: 1, done: false }
do.next(); // { value: 2, done: false }
do.next(); // { value: 3, done: true }
do.next(); // { value: undefined, done: true }
複製程式碼

這是一種解決辦法,詳情可以看阮一峰老師的es6標準入門(作者不想展開)。

2. promise

let eat = () => {
    return new Promise((resolve, reject) => {
        resolve('俺吃好啦,給你盤子')
    })
}

eat.then( res => {
    //吃完後給你再洗盤子
    let washResult = washDishes(res);
    return washResult;
})
.then(res => {
    //洗完盤子後,你媽媽甚至還獎勵你吃冰淇淋!
    eatIceCream(res)
})
複製程式碼

這個可是好東西啊,promise就像是你在追求的女孩阿珍。

他有三種狀態:等待中(pending) 完成了 (resolved) 拒絕了(rejected)。

你給阿珍送了跟項鍊,阿珍在想,到底要不要接收阿強呢?這個就是pending 等待中。

阿珍覺得你挺不錯的,三圍都是180,嗯。接受你了!我們阿強時候親吻阿珍了。這個就是resovled 完成了。

阿珍覺得阿偉比你帥,不想接受你的求愛,拒絕你了,整個流程碰到錯誤了有問題了。這就是reject 拒絕了

這個就是簡單的promise了。

3. async/await

async function eat () {
    let washResult = await washDishes();
    let eatIceCream = await buyIceCream(washResult);
    let eatCake = await buyCake(eatIceCream);
    //你媽媽看你吃的多,再獎勵大胖兒子一個cake!
}
複製程式碼

這個東西呢,其實就是一層語法糖,加上async命令的函式,會return出一個promise。

意思和阿強愛上了阿珍一個道理,只是追求阿珍的路上方便了不少。


回到題目!你知道什麼是回撥地獄嗎?你可以這樣說。

  1. 回答回撥函式是啥?
  2. 為什麼會有回撥地獄?
  3. 我該如何解決?
  4. 擴充套件你的解決辦法。
  5. 擴充套件你的解決辦法。
  6. 擴充套件你的解決辦法。

例如作者自己對這個問題的解答如下:

1.因為javascript是單執行緒的,所以有些需要等待的地方,需要使用回撥函式。
2.由於某些業務的問題,在程式碼中會一次性寫會多層的回撥巢狀,回撥巢狀後的程式碼的維護難度,和無法排除bug。這個就被稱作回撥地獄。
3.我在工作中,一般處理的方式是使用promise或者async函式。
4.promise由於xxxx 對於開發這種多層巢狀的程式碼很方便,降低了程式碼的維護難度等等。
5.promise是XXX時新增的,擁有著xxxx的特性等等。
6.promise下面的all函式我也經常用到xxxxxxx
7.你甚至還可以手寫個promise!
複製程式碼

好了這篇需要講的東西已經結束了。
接下來估計會有一堆堆關於面試的文章。
如果您有收穫或者疑問請在下方評論,求贊!謝謝觀看到這裡。

相關文章