解決回調函數帶來的回調地獄

一、什麼是回調函數?

回調函數一個經過指針調用的函數。若是你把這個指針做爲參數傳給另外一個函數,當這個指針指向的函數被調用的時候,咱們就說和這個函數是回調函數。回調函數不是由函數的實現方直接調用的,而是在特定的時間或者條件,由另外一方函數調用。編程

二、回調函數的做用

把調用者和被調用者區分開,所用調用者不關心誰是被調用者,它只需知道存在一個具備特定原型的和限制條件的被調用者函數。簡而言之,回調函數容許用戶把須要調用的函數做爲一個指針傳給另外一個函數,使程序更加靈活。promise

三、回調函數的缺點:回調地獄

回調地址的本質:①嵌套函數存在嚴重的耦合,牽一髮而動全身。②錯誤處理比較艱難,不能使用try catch 和不能直接return。bash

四、如何解決回調地獄?

三個原則
  • 保持代碼淺
  • 模塊化
  • 處理每個錯誤

實現

  • 拆解function,將各部拆解爲一個一個的function。
  • 事件發佈/監聽模式
一方面監聽事件發生,若是發生執行相應的回調,另外一方面,監聽操做的完成,當操做完成時進行相應的回調。
複製代碼
  • Promise
readFile('./sample.txt').then(content => {
    let keyword = content.substring(0, 5);
    return queryDB(keyword);
}).then(res => {
    return getData(res.length);
}).then(data => {
    console.log(data);
}).catch(err => {
    console.warn(err);
});
複製代碼
  • generator
// 咱們的主任務——顯示關鍵字// 使用yield暫時中斷下方代碼執行// yield後面爲promise對象
const showKeyword = function* (filepath) {
    console.log('開始讀取');
    let keyword = yield readFile(filepath);
    console.log(`關鍵字爲${filepath}`);
}
// generator的流程控制
let gen = showKeyword();
let res = gen.next();
res.value.then(res => gen.next(res));
複製代碼
  • async/await
能夠看到,上面的方法雖然都在必定程度上解決了異步編程中回調帶來的問題。
  • function拆分的方式其實僅僅只是拆分代碼塊,時常會不利於後續維護;
  • 事件發佈/監聽方式模糊了異步方法之間的流程關係;
  • Promise雖然使得多個嵌套的異步調用可以經過鏈式的API進行操做,可是過多的then也增長了代碼的冗餘,也對閱讀代碼中各階段的異步任務產生了必定干擾;
  • 過generator雖然能提供較好的語法結構,可是畢竟generator與yield的語境用在這裏多少還有些不太貼切。
所以,這裏再介紹一個方法,它就是es7中的async/await。

簡單介紹一下async/await。基本上,任何一個函數均可以成爲async函數,如下都是合法的書寫形式:異步

const printData = async function (filepath) {
   let keyword = await readFile(filepath);
   let count = await queryDB(keyword);
   let data = await getData(res.length);
   console.log(data);
});
printData('./sample.txt');
複製代碼
相關文章
相關標籤/搜索