回調地獄


何為回調函數

1 setTimeout(function () {
2   console.log('callback...');
3 }, 1000);

此延時定時器中的function就是我們常說的回調函數,回調函數常常滿足三個特征

  • 我們自己定義的
  • 我們自己沒去執行
  • 最終被其它人(瀏覽器的ajax模塊,定時器模塊...)執行了

 

何為回調地獄

 1 setTimeout(function (name) {
 2   var catList = name + ',';
 3 
 4   setTimeout(function (name) {
 5     catList += name + ',';
 6 
 7     setTimeout(function (name) {
 8       catList += name + ',';
 9 
10       setTimeout(function (name) {
11         catList += name + ',';
12 
13         setTimeout(function (name) {
14           catList += name;
15 
16           console.log(catList);
17 
18         }, 1, 'Lion');
19 
20       }, 1, 'Snow Leopard');
21 
22     }, 1, 'Lynx');
23 
24   }, 1, 'Jaguar');}, 1, 'Panther');

由於回調函數是異步的,在上面的代碼中每一層的回調函數都需要依賴上一層的回調執行完,所以形成了層層嵌套的關系最終形成類似上面的回調地獄,但代碼以此種形式展現時無疑是不利於我們閱讀與維護的,此時就要想辦法改進這種代碼形式。

 

初次改進

    var catList = '';

    setTimeout(getPanther, 1, 'Panther');

    function getPanther(name) {
        catList += name + ',';
        setTimeout(getJanguar, 1, 'Janguar');
    }

    function getJanguar(name) {
        catList += name + ',';
        setTimeout(getLynx, 1, 'Lynx');
    }

    function getLynx(name) {
        catList += name + ',';
        setTimeout(getSnowLeopard, 1, 'Snow Leopard');
    }

    function getSnowLeopard(name) {
        catList += name + ',';
        setTimeout(getLion, 1, 'Lion');
    }

    function getLion(name) {
        catList += name;
        setTimeout(print, 1);
    }

    function print() {
        console.log(catList);
    }

將匿名函數命名

雖然匿名函數使用方便,但是不利於我們閱讀與書寫,所以我們選擇將回調函數單獨的拿出來並命名,寫成如上形式,這樣看上去就要比第一次的代碼優雅清晰很多。需要注意的是上面的代碼相比之前有了幾點改變。

1. catList變成了全局變量

2. 函數的作用域發生了變化,從局部作用域變成了全局作用域,所以才需要將catList變成全局變量以保證每個函數都可以訪問的到

通常情況下我們不希望有全局變量污染環境,並且上面的代碼還有一些可以復用的空間,可以看到我們在每個函數中都重復的調用定時器,所以我們可以再來改進一下上面的代碼。

 

再次改進

 

 1     function buildCatList(list, returnVal, fn) {
 2         setTimeout(function (name) {
 3             var catList = list === '' ? name : list + ',' + name;
 4             fn(catList);
 5         }, 1, returnVal);
 6     }
 7 
 8 
 9     buildCatList('', 'Panther', getJanguar);
10 
11     function getJanguar(list) {
12         buildCatList(list, 'Janguar', getLynx);
13     }
14 
15     function getLynx(list) {
16         buildCatList(list, 'Lynx', getSnowLeopard);
17     }
18 
19     function getSnowLeopard(list) {
20         buildCatList(list, 'Snow Leopard', getLion);
21     }
22 
23     function getLion(list) {
24         buildCatList(list, 'Lion',print);
25     }
26 
27     function print(list) {
28         console.log(list);
29     }

 

定時器中的回調函數處在外層函數中的作用域內,並通過參數傳入,沒有產生全局變量,沒有重復代碼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM