課程目標

  • 認識 callback hell

課程內容

在一般「同步程式設計語言」中,程式碼執行的順序,就是一行一行跑下來,很容易理解

但 JavaScript 是「非同步程式設計語言」,很多時候,執行順序不是一行一行跑下來

為了讓用戶能持續流暢操作瀏覽器介面,工程師需要在會用到「非同步」的地方使用特殊寫法

最原始、也最單純的做法是使用 callback function,也就是把要在非同步任務結束後才跑的任務,寫在 callback function 傳進去

以 jquery 最原始的 ajax 處理為例

$.get(url, params, (data) => {
  // do something with data
})

第三個參數,也就是箭頭函式的部份,就是所謂的 callback function


當年的前端工程師,在一開始覺得這樣寫沒問題,但是當網頁應用程式越來越複雜之後

發現在需要連續執行多個非同步任務時,會需要不斷傳 callback function 進去更深層

最後導致的結果,就是所謂的「callback hell」!這讓程式碼很難讀、很難維護!

$.get(url, params, (data) => {
  // do something with data to get params2

  $.get(url2, params2, (data) => {
    // do something with data to get params3

    $.get(url3, params3, (data) => {
      // do the final task with data
    });
  });
});

這樣描述比較抽象,來跟著作業,試著用當年的方式開發看看吧!

課後作業

讓我們時光倒轉,回到 2000 年代,體驗一下當時的開發方式

請使用 https://jsfiddle.net/ 寫作業

請載入 jquery 套件,並且用 jQuery.get() 來處理 ajax

<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>

假設你身為前端工程師,正在開發電商網站

今天,產品經理跟你說,為了提升 UX(用戶體驗)

希望能在網頁上顯示「最近一次的訂單內容」,就像這樣:

尊貴的客戶您好,您上次的消費內容是:
訂單編號:XXX
訂單內容:XXX
訂單金額:XXX
希望這次也能有機會服務您!

目前後端工程師提供了三組 API 給你使用

使用當年的 jquery 寫法會像是下面這樣:

取得當前登入用戶的資料

為了簡化起見,你不用實作「登入、驗證」等等功能

就當作用戶已經登入了,請直接呼叫這個 API 即可

$.get("https://codelove.tw/fake-api/get-current-user", {}, (res) => {
    console.log('the current user id is:' + res.data.user.id)
});

取得指定用戶的全部訂單

$.get("https://codelove.tw/fake-api/get-orders", { user_id: 1 }, (res) => {
  console.log('get ' + res.data.orders.length + ' orders');
});

取得指定訂單的內容細節

$.get("https://codelove.tw/fake-api/get-order-details", { order_id: 1 }, (res) => {
  console.log('the order id is #' + res.data.order.id);
  console.log('the order content is ' + res.data.order.content);
  console.log('the order amount is $' + res.data.order.amount);
});
  • 請依序呼叫這三個 API,來完成這次需要的功能
  • 把第一個 API 拿到的 user id 放進第二個 API 呼叫
  • 把第二個 API 拿到的最後一個 order id 放進第三個 API 呼叫
  • 把第三個 API 拿到的資料,顯示在網頁上

請注意,不要使用現代的非同步寫法,請使用 callback hell 的寫法,也就是:

  • 在第一個 API 的 callback function 裡面呼叫第二個 API
  • 在第二個 API 的 callback function 裡面呼叫第三個 API
  • 在第三個 API 的 callback function 裡面完成最終需要的功能

寫完之後,你應該會看到有三層深度的巢狀 callback 傳遞!

這就有一點悲慘了,有點 callback hell 的感覺!

做出以上功能,你就完成這次的課程目標了!


歡迎將作業成果,在下方留言,跟大家分享,讓大家給你一些回饋!

可以將每課學到的觀念、關鍵字,丟到網路上去搜尋、研究一下!

發問請在「討論專區」為主,或者分享學習筆記、寫學習心得!

貼文都會出現在個人檔案頁面,成為學習歷程、部落格紀錄!

未來面試時,分享給面試官看,會讓人知道你的積極程度!


共有 7 則留言

作業繳交 https://jsfiddle.net/gk5neq6z/54/

按讚的人:

寫得很好,順利完成!

作業繳交 https://jsfiddle.net/jason60810/9zd0wpjL/11/

可以使用 array.at(-1).id 來取得最後一個 order 的 id 不用 array[ array.length - 1 ].id

按讚的人:

寫得很好,順利完成! 感謝補充資訊!

作業繳交 https://jsfiddle.net/hung19091/ys42xpj1/2/

題外話: 之前為了寫Switch(模擬手把)的外掛 「等待N秒鐘」的功能是用await去實現 那個時候就寫過兩層的call back hell...(囧)

按讚的人:

寫得很好,順利完成!

交作業 https://jsfiddle.net/birdie2019/6dm07yo8/20/

按讚的人:
免費

邁向資深之路:非同步 JS 訓練(一)—— 從 Callback Hell 到 Promise 介面

工作了很多年,還是搞不太懂 promise、async/await 是什麼嗎?用這份作業包一次搞定!


👉 身份:資深全端工程師、指導過無數人半路出家轉職 👉 使命:打造 CodeLove 成為優質新手村,讓非本科也有地方自學&討論