🔍 搜尋結果:JS

🔍 搜尋結果:JS

挑戰串接CodeLove的API

成品連結:https://codingdark.github.io/program/2023/09/18/API-Test.html ##第一步 架部落格 最初看到站長的貼文,提供了本站的API 並且鼓勵大家自架部落格,來嘗試串API 看到文章的當下,覺得有點難度(沒用過github page,API也不熟) 不過看到站長提供的關鍵字`setup a personal blog with github pages` 最終還是決定先google看看 查了之後,發現近年的gitbub簡化了很多 都可以自動部署,根本就是一鍵架站 外加原始碼開源,很多東西都能自己改 所以光是部落格就玩了一天XD 因為本站為CodeLove 愛寫扣 我就創了一個CodingDark 闇寫扣 表示致敬本站 & 本人的中二風格 ##第二步 串API 因為不熟的關係,所以決定先隨便串 呼叫API之後,把data印在console.log 大致上看了一下資料格式 使用上其實就類似陣列,非常方便 沒有想像中的難 確認API可以正常呼叫後 陸續加入一些功能 比方說,用Table把文章列表排整齊、加上[Read more]按鈕 先讓json資料,轉換成網頁能呈現出來的[資訊] ##第三步 程式碼優化 到這邊為止,網頁的畫面已經差不多定型了 剩下的就是回頭檢視程式碼 考量到後續維護 盡可能把重複的程式碼,包裝成function 或是把一群散亂的變數,包裝成object 最後,為了方便擴充文章列表 將原本是寫死的HTML Dom 改成動態產生 目前的部落格頁面 點進去會撈出站長、Tony,以及我的文章列表 後續若想要列出其他使用者的文章 只需新增`setTable(userAccount)`即可 ##結尾 感謝站長提供有趣的API 讓大家可以有練習的機會 雖然目前我在工作上,沒接觸過API 但經過這次的練習,以後若是真的有需要用到 可以更快上手

寫單元測試的五個技巧分享

測試程式碼是軟體開發最重要的方面之一,因為它可以確保產品的品質、可擴展性和可靠性。 但是,如果沒有任何指導,編寫有效的測試可能會很困難。測試程式碼可能比實際功能的程式碼更複雜、更難維護! 原文出處:https://dev.to/one-beyond/the-5-principles-of-unit-testing-1p5f ## 1.精簡和準確的測試 測試程式碼必須**簡單且易於使用**。任何查看測試的人都應該立即知道測試的內容及其目的是什麼。開發測試應該以很少的精力和時間投入帶來巨大的價值。 > _您是否需要超過 30 秒的時間來閱讀和理解您的測試?重寫它!_ 測試“覆蓋率”是重點嗎?不! **僅測試必要的部份就好**。為了敏捷性和簡單性,最好放棄一些測試,**只測試主要業務邏輯和主要邊緣情況就好**。 ## 2.測試行為,而不是元件實作 不要檢查程式碼中的每一行和內部變數。測試時,您應該**專注於結果**。即使方法內的程式碼被重構,結果也應該永遠保持不變! 這樣,如果程式碼庫發生更改,您**不需要重寫測試**。 ``` // Wrong ❌ - Test behaviour describe('Evaluation Service', () => { describe('Register Students', () => { it('Should add new students to the evaluation service', () => { const studentJosh = { id: 1, name: 'Josh McLovin', average: 6.98, } evaluationService.addStudent(studentJosh) expect(evaluationService._students[0].name).toBe('Josh') expect(evaluationService._students[0].average).toBe(6.98) }) }) }) ``` ``` // Right ✅ - Test behaviour describe('Evaluation Service', () => { describe('Register Students', () => { it('Should add new students to the evaluation service', () => { const studentJosh = { id: 1, name: 'Josh McLovin', average: 6.98, } evaluationService.addStudent(studentJosh) expect(evaluationService.getStudentAverage('Josh')).toBe(6.98) }) }) }) ``` ## 3. 關於命名和結構:AAA 模式 您是否曾經遇到過名為“_它應該[...]正確_”的失敗測試,但花了幾分鐘才找到問題所在? 良好命名和結構可以讓您快速且準確地找到任何失敗的測試,最終節省您的寶貴時間。因此,讓我們深入探討兩個關鍵原則,以便在下次測試時牢記: ### 3.1 經過深思熟慮的測試命名: 在命名您的測試時,請嘗試合併以下資訊:   - **正在測試什麼**?   - **什麼情況**?   - **預期結果**是什麼? ``` // Right ✅ - Test naming // 1. What is being tested: describe('Evaluation Service', () => { describe('Evaluate Students', () => { // 2 & 3. Context and expected result it('If the student grade is below the minimum grade, student should be suspended', () => { const students = [ { name: 'Mark', grade: 4.25 }, { name: 'Colin', grade: 6.7 }, { name: 'Ben', grade: 5.3 }, ] const result = evaluationService.evaluateStudents({ students, minGrade: 5 }) expect(result['Mark']).toBe('suspended') }) }) }) ``` ### 3.2 測試程式碼結構的AAA模式: 如果您想維護一個可讀且易於理解的測試套件,請按如下方式建立測試: - **安排**:設定模擬所需情況所需的所有程式碼。這可以包括初始化變數、模擬響應、實例化被測單元等。 - **行為**:執行正在測試的內容,通常在一行程式碼中。 - **斷言**:檢查得到的結果是否為預期的結果。與上面的一樣,這應該只需要一行。 ``` // Right - AAA Testing Pattern describe('Evaluation Service', () => { describe('Average Calculation', () => { it('Should calculate the average grade of all the students', () => { // Arrange: create an object with the student names and their grades const students = [ { name: 'Mark', grade: 4 }, { name: 'Colin', grade: 10 }, { name: 'Ben', grade: 7 }, { name: 'Tim', grade: 3 }, ] // Act: execute the getAverage method const avg = evaluationService.getAverage(students) // Assert: check if the result is the expected one -> (4+10+7+3)/4 = 6 expect(avg).toEqual(6) }) }) }) ``` ##4。確定性和隔離測試 如果一個失敗的測試使您的整個套件變紅,那麼您可能沒有以正確的方式處理它! 測試應該**獨立和隔離**,一次針對並處理一個特定邏輯,從而完成更快、更穩定的測試套件。 **如果您不**獨立編寫測試會發生什麼? - 您將無法找出錯誤和問題的**確切原因和位置**。 - 重構測試時,您必須**更新和同步多個測試**。 - 您將無法以任何順序執行測試,這可能會導致**破壞或跳過某些斷言或期望**。 ## 5。基於屬性的測試和真實資料 厭倦了在測試中編寫大量可能的輸入?基於屬性的測試可以為您做到這一點!……那是什麼? 基於屬性的測試建立了數百種可能的組合,強調了測試並**增加了發現以前未被注意到的錯誤的機會**。這種方法甚至可以傳回可能導致意外結果的輸入。 [JSVerify](https://github.com/jsverify/jsverify) 或 [Fast-Check](https://github.com/dubzzz/fast-check) 等函式庫提供了促進基於屬性的測試的基本工具。 但是,如果您不想深入進行如此廣泛的測試,那麼盡可能利用**真實資料**至關重要。像“abc”或“1234”這樣的輸入可能會在實際失敗時錯誤地通過測試。 ``` // Wrong ❌ - False Positive - Test that passes even though it shouldn't class EvaluationService { _students = []; addStudent(student) { // Add the student if the name has no numbers if(!student.name.matches(/^([^0-9]*)$/)){ this._students.push(student); } } } describe('Evaluation Service', () => { describe('Register Students', () => { it('Should add students to the Evaluation service', () => { const mockStudent = { id: 2, name: 'username', average: 7 } // Won't fail because the name is a string without number -> We are not checking what happens if the user // inputs a name with a number. evaluationService.addStudent(mockStudent) expect(evaluationService.getStudentAverage('username')).toBe(7) }) }) }) // In the example above, we are making a test so the test passes, instead of looking for edge cases with realistic data ``` ##額外提示! 如果您在測試元件中的任何邏輯時遇到困難,這可能反映出您也許應該將元件邏輯分解為更小、更容易且可測試的程式碼片段! 總而言之,遵循此最佳實踐可能會帶來一種新的、可讀且可維護的方法來測試您喜愛的生產程式碼。 > 經過測試的應用程式才是可靠的應用程式!

回答網友提問:雲科碩畢,上班中,考慮轉職軟體工程師,請問有建議嗎?

阿川收到網友提問如下: > 阿川你好: > 我的背景是雲科碩畢業,算是混上去的,現在打算轉職軟工,由於有在工作,所以打算先以自學為主3-6個月,看情況後決定是否報名資策會。 > 想請問一下,目前比較希望能夠走後端(網頁開發類),查了一些相關資訊,網頁似乎比較友善,未來有機會再往其他產業前進! > 搜尋了一下職務,網頁類的後端其實也需要html css js 前端三本柱。 > 我想問的是: > 1.是否直接開始學三本柱比較好?(反正前面的作品、入職也會需要)且 有了js基礎還能繼續學習node.js(後端)。 不過又礙於可能比較沒方向,會變成說學一學越來越往前端過去? > 2.先以門檻較低的前端入門、入職以後再好好思考想專精哪一端之類的 or 以c#為主學習,再慢慢學三本柱,資料庫等等 > 3.前端的切版技術等等,是否真的必要? 本人美感很差.. 兩個問題的考量的都是想說是否先以java,c#等後端去建立程式概念或許比較好。 > 文有點長,再麻煩您給我一些建議了,也想順便問一下,有看到您有提供免費html css 以及付費js課程,能在跟您要這方面的資訊嗎? 這些問題很好,我一樣公開回答,給類似狀況的人參考。 --- 簡單回答如下: 1、不論前後端 html 跟 css 都要會,所以這兩個可以先學。js 的話後端不用學精,稍微會寫就好,除非你是寫 node 至於最後會去前端或後端的職缺,都可以,先不用擔心這個,不然你就找全端的職缺也可以 2、後端需要學資料庫、基本伺服器管理,語言的話 C# 或 java 或 php 或 python 或 node 之類的都可以 3、前端做久了,因為常常跟設計師合作,會慢慢具備一點設計素養。如果對「UI 設計」有興趣是最好,沒有的話,倒也沒關係。美感可以慢慢訓練,先不用畫地自限 --- 總結來說,我建議你就先學 html 與 css,之後再看你用 html css 把網頁寫漂亮有沒有興趣,如果喜歡把畫面弄漂亮,就多學一點前端。如果只想做工程,就專心在後端吧。這些問題學了 html css 之後會更清楚,先不用太糾結。不然你就以全端為方向也可以,前後端都寫!你就先挑一個免費 or 便宜的線上課程,先開始寫寫看再說 先開始行動,會更清楚自己在做什麼,之後需要花大錢去報名補習班時,也會比較有把握 就算你一開始只寫前 or 後端,很多人上班之後,因為工作需求,還是慢慢有具備全端的技能 其實不用太排斥全端,都寫的話,一來在公司能做的事情變多、能應徵的機會變多,二來還可以自己用業餘時間寫 side project,因為一個人就能做完全部事情,所以會很好玩,也對職業生涯很有幫助 關於我設計的免費 html css 教材,請參考:https://codelove.tw/courses/frontend-beginner 另外,轉職過程會有諸多問題,可以加我們 LINE 群多跟大家討論:https://line.me/ti/g2/nipkjq2WoZPKX5dTn9tE9266aEOt6EOICFGa1g --- 以上,簡單分享,希望對大家有幫助!

非同步 JS 訓練二:第6課 ── 認識 async/await 語法與收尾處理

## 課程目標 - 認識 async/await 語法與收尾處理 ## 課程內容 接著來學 async/await 的收尾處理吧! 說起來也神奇,只要加上 `finally` 區塊就可以了! ``` try { const data1 = await $.get(url, params); // do something with data to get params2 const data2 = await $.get(url2, params2); // do something with data to get params3 const data3 = await $.get(url3, params3); // do the final task with data } catch (err) { alert('Something went wrong.'); } finally { // hide the loading icon } ``` 因為 `try/catch/finally` 本來就是一般同步程式設計語言會用到的錯誤處理語法 所以這整段程式碼,看起來跟一般的同步程式設計,幾乎一模一樣! 就是這麼奇妙!應該不用我多解釋什麼了! --- 多補充一句,我個人開發比較複雜的前端應用時,最常用的語法就是這種! 我認為 `async/await` 加上 `try/catch/finally` 是最簡潔有力的! 錯誤訊息提示、忙碌狀態提示,通通都有了,很輕易就做出 UX 很棒的應用程式! ## 課後作業 請拿出第三課的作業,我們來改善這個頁面的 UX(使用者體驗),明確提示「忙碌中」這個狀態 --- - 請用 html 元素,在頁面中加入一段 `讀取中,請稍等...` 的訊息,這個元素預設不顯示 - 在開始呼叫 API 的地方,用 js 操作來讓那個 html 元素顯示 - 在結束呼叫 API 的地方,使用 `finally` 語法,用 js 操作來讓那個 html 元素隱藏 做出以上功能,你就完成這次的課程目標了!

非同步 JS 訓練二:第5課 ── 認識 promise chain 鏈接與收尾處理

## 課程目標 - 認識 promise chain 鏈接與收尾處理 ## 課程內容 接著來學 promise chain 的收尾處理吧! 繼續拿 jquery 當範例,只要在上次的 promise chain 最後,加上 `.always()` 就可以了! ``` $.get(url, params).then((data) => { // do something with data to get params2 return $.get(url2, params2); }).then((data) => { // do something with data to get params3 return $.get(url3, params3); }).then((data) => { // do the final task with data }).catch((err) => { alert('Something went wrong.'); }).always(() => { // hide the loading icon }); ``` 很簡潔有力吧! ### ⚠️特別注意事項⚠️ 因為某些歷史因素,jquery 包裝的 promise 跟現在瀏覽器原生的 promise 有點不太一樣! 原生的 promise 是 `.finally()`,而不像 jquery 是 `.always()`! 為了教學方便,本課&作業都用 jquery 示範,實務上如果看到 `.finally()` 請不要意外! 都是類似東西,知道這樣就好! ## 課後作業 請拿出第二課的作業,我們來改善這個頁面的 UX(使用者體驗),明確提示「忙碌中」這個狀態 --- - 請用 html 元素,在頁面中加入一段 `讀取中,請稍等...` 的訊息,這個元素預設不顯示 - 在開始呼叫 API 的地方,用 js 操作來讓那個 html 元素顯示 - 在結束呼叫 API 的地方,使用 `always()`,用 js 操作來讓那個 html 元素隱藏 寫完之後,你應該會發現不但 callback hell 改善了、錯誤處理有了、連 UX 都改善了! 做出以上功能,你就完成這次的課程目標了!

非同步 JS 訓練二:第4課 ── 認識 callback hell 與收尾處理

## 課程目標 - 認識 callback hell 與收尾處理 ## 課程內容 研究完 callback hell、promise chain、async/await 的錯誤處理 接著來用三課的時間,分別研究收尾處理吧! 讓我們先從 callback hell 的寫法開始! --- 什麼是收尾處理? 其實就是,有些事情,不論任務執行成功 or 失敗,都固定要執行 這種事情,可以在 success callback 跟 error callback 最後都寫,但這樣就重複寫了,很煩! 所以就有所謂的收尾處理,讓你寫一次就好了 如果繼續拿 jquery 做範例,看起來會像這樣: ``` $.ajax({ url: url, data: params, success: (res) => {}, error: (res) => {}, complete: () => {}, }); ``` 其實,就是再多一個 callback function 而已!很單純吧! 在連續多個 ajax call 的時候,錯誤處理機制,再加上收尾處理機制,想想看 callback hell 會有多嚴重! --- 看到這邊,你可能會想,到底什麼事情需要在收尾機制處理呀? 其實,以我個人經驗來說,需要放進收尾處理的東西,其實很少 最常見的就是處理畫面上的「載入中,請稍等...」的文字,或者是畫面上「用來代表忙碌中的一個旋轉的圖示」 不論任務執行結果,都需要把這些文字、圖示隱藏 老實說,很多人根本連「忙碌中」這個狀態也沒做,導致 UX 不太好 所以實務上,如果你發現專案中不太會寫收尾處理,那也算正常,你就知道有這功能可以用即可 ## 課後作業 在第一課的作業,你已經體驗到了 callback hell 與錯誤處理的悲劇 忍耐一下,這一課要再體驗一下當年工程師的痛苦:加上收尾處理吧! 請拿出第一課的作業,我們來改善這個頁面的 UX(使用者體驗),明確提示「忙碌中」這個狀態 --- - 請用 html 元素,在頁面中加入一段 `讀取中,請稍等...` 的訊息,這個元素預設不顯示 - 在開始呼叫 API 的地方,用 js 操作來讓那個 html 元素顯示 - 在結束呼叫 API 的地方,使用 `$.ajax()` 的 `complete` 參數,用 js 操作來讓那個 html 元素隱藏 寫完之後,你應該會發現,有點難寫,而且顯示/隱藏的時機,有點奇怪! 如果想要讓顯示/隱藏的時機,完全正確,那就會重複很多一樣的 code! 別懷疑,就是這麼難寫、這麼奇怪!這就是當年前端開發的為難之處! 做出以上功能,你就完成這次的課程目標了!

非同步 JS 訓練二:第3課 ── 認識 async/await 語法與錯誤處理

## 課程目標 - 認識 async/await 語法與錯誤處理 ## 課程內容 在非同步訓練一的課程,我們初步體驗到 async/await 寫起來的感覺,效果不錯! 這次來試著加上錯誤處理! 說起來也神奇,只要使用 `try/catch` 語法包起來就可以了! ``` try { const data1 = await $.get(url, params); // do something with data to get params2 const data2 = await $.get(url2, params2); // do something with data to get params3 const data3 = await $.get(url3, params3); // do the final task with data } catch (err) { alert('Something went wrong.'); } ``` 因為 `try/catch` 本來就是一般同步程式設計語言會用到的錯誤處理語法 所以這整段程式碼,看起來跟一般的同步程式設計,幾乎一模一樣! --- 上次我們說過:每次只要看到 await,就要去想「現在是去剝開 promise 的 then 裡面,拿出最後回傳的內容!」 現在可以多補充一句:「如果 await 後面的非同步任務跑失敗,就會直接 throw exception(拋出例外)」 有點看不懂沒關係,就先跟著使用方式,照做即可! 工作上多用幾次之後,會逐漸抓到感覺! ## 課後作業 這一次的作業,我們要延續「非同步 JS 訓練一:第3課」的內容,並且加上錯誤處理 https://codelove.tw/@howtomakeaturn/post/bapzbx 請找出你上次寫的作業,把上次的三組 API,換成以下這三組 ``` https://codelove.tw/fake-api/get-current-user-unstable ``` ``` https://codelove.tw/fake-api/get-orders-unstable ``` ``` https://codelove.tw/fake-api/get-order-details-unstable ``` --- 幾點注意事項如下: - 繼續用 `$.get()` 來呼叫 API 即可 - 寫一個 `try/catch` 就好了,不要寫成多個 `try/catch` - 任何一個 API 失敗時,請 `alert('抱歉,系統出了點問題,請稍後再試一次。');` 寫完之後,你會發現,整段程式碼看起來很像「一般程式語言中,同步程式設計」的寫法! 連 `try/catch` 看起來都跟常見程式語言的錯誤處理,一模一樣! 做出以上功能,你就完成這次的課程目標了!

非同步 JS 訓練二:第2課 ── 認識 promise chain 鏈接與錯誤處理

## 課程目標 - 認識 promise chain 鏈接與錯誤處理 ## 課程內容 在非同步訓練一的課程,我們初步體驗到 promise chain 寫起來的感覺,效果不錯! 這次來試著加上錯誤處理! 只要在上次的 promise chain 最後,加上 `.catch()` 就可以了! ``` $.get(url, params).then((data) => { // do something with data to get params2 return $.get(url2, params2); }).then((data) => { // do something with data to get params3 return $.get(url3, params3); }).then((data) => { // do the final task with data }).catch((err) => { alert('Something went wrong.'); }); ``` 上面這段程式碼,總共發了三次 ajax,不論是哪一次失敗,都會被最後的 `.catch()` 捕捉到喔! 很簡潔有力吧! --- 看到這邊,你可能會心想,可是上次 callback hell 的寫法,我可以針對三個 api 分別寫不同的 callback,顯示不同的錯誤訊息耶! 這次只能寫一個 callback,給一個籠統的系統錯誤,好像 UX 不夠好呀? 其實你說的沒錯!這樣寫的確會有這問題! 但我個人經驗是,系統跑 ajax 失敗,其實整體 UX 已經很不好了,用戶已經覺得這網站很難用了 明確顯示哪個步驟失敗,其實幫助不大。就一律在訊息中「道歉&懇請用戶再試一次&告知可以回報客服」就好了! (如果真的要顯示不同錯誤訊息,是有其他 promise 比較複雜的寫法,這一課先不談論) ## 課後作業 這一次的作業,我們要延續「非同步 JS 訓練一:第2課」的內容,並且加上錯誤處理 https://codelove.tw/@howtomakeaturn/post/8aAPD3 請找出你上次寫的作業,把上次的三組 API,換成以下這三組 ``` https://codelove.tw/fake-api/get-current-user-unstable ``` ``` https://codelove.tw/fake-api/get-orders-unstable ``` ``` https://codelove.tw/fake-api/get-order-details-unstable ``` --- 幾點注意事項如下: - 繼續用 `$.get()` 來呼叫 API 即可 - 寫一個 `.catch()` 就好了,不用特別寫三種錯誤訊息 - 任何一個 API 失敗時,請 `alert('抱歉,系統出了點問題,請稍後再試一次。');` 寫完之後,你應該會看到多個 `.then()` 串接在一起,不再出現多層深度的巢狀 callback 傳遞了! 而且錯誤處理的部份,也比之前改善很多,簡單又清楚! 做出以上功能,你就完成這次的課程目標了!

非同步 JS 訓練二:第1課 ── 認識 callback hell 與錯誤處理

## 課程目標 - 認識 callback hell 與錯誤處理 ## 課程內容 在非同步訓練一的課程,我們初步體驗到 callback hell 寫起來的感覺 其實,當年的工程師,面對的真正痛苦,比上次體驗到的更嚴重! 非同步任務,常常需要處理「任務失敗」的情況 比方說「主機回應超時」、「資料庫連線失敗」、「主機斷線」等等情況 按照 javascript 的慣例,就是多寫一個 callback function 處理這種情況 比方說函式可以設計成這樣 ``` runAsyncTask(success, error) ``` 使用者只要分別傳進「成功後的處理」以及「失敗後的處理」即可 ``` runAsyncTask(() => { alert('執行成功!'); }, () => { alert('執行失敗,請等等重新嘗試!'); }); ``` 如果繼續拿 jquery 做範例,看起來會像這樣: ``` $.ajax({ url: url, data: params, success: (res) => {}, error: (res) => {}, }); ``` 註1:他不是設計成兩個參數,而是物件的兩個屬性,但意思一樣 註2:沒辦法繼續用上次的 `$.get()`,他沒有設計錯誤處理的 callback。所以改用 `$.ajax()` 光看這樣可能還好,畢竟寫 javascript 就是很常到處寫 callback 傳來傳去 可是,你能想像連續呼叫多個 ajax 時,再加上錯誤處理機制,callback hell 會有多嚴重嗎! 來跟著作業,體驗一下,試著用當年的方式開發看看吧! ## 課後作業 這一次的作業,我們要延續「非同步 JS 訓練一:第1課」的內容,並且加上錯誤處理 https://codelove.tw/@howtomakeaturn/post/lqOkWq 請找出你上次寫的作業,把上次的三組 API,換成以下這三組 ``` https://codelove.tw/fake-api/get-current-user-unstable ``` ``` https://codelove.tw/fake-api/get-orders-unstable ``` ``` https://codelove.tw/fake-api/get-order-details-unstable ``` 這三組 API 很不穩定,每組 API 都有 1/3 的機率會抓資料失敗! 實務上不可能有 API 爛成這樣,通常失敗率會在 1% 以下,這次是方便測試,我故意寫的 API --- 幾點注意事項如下: - 不要使用現代的非同步寫法,請使用 callback hell 的寫法 - 使用 `$.ajax()` 來呼叫 API - 使用 `$.ajax()` 的 `success` 參數來處理成功的情況 - 使用 `$.ajax()` 的 `error` 參數來處理失敗的情況 - 第一個 API 失敗時,請 `alert('讀取用戶失敗,請稍後再試一次。');` - 第二個 API 失敗時,請 `alert('讀取訂單列表失敗,請稍後再試一次。');` - 第三個 API 失敗時,請 `alert('讀取訂單細節失敗,請稍後再試一次。');` 寫完之後,你應該會看到有三層深度的巢狀 callback 傳遞! 而且比上次的情況還離譜!加上錯誤處理之後,整段 code 更加難以閱讀、維護! 這就是當年前端工程師,每天工作面臨的狀況!很悲慘吧! 做出以上功能,你就完成這次的課程目標了!

非同步 JS 訓練一:第3課 ── 認識 async/await 語法

## 課程目標 - 認識 async/await 語法 ## 課程內容 體驗過 promise 之後,你會發現雖然改善很多,但還是有一點點麻煩 因為你需要 `.then()` 還有 `return`,而且,還是有一層巢狀結構 因此,工程師在 ES2017 又提出了一個解決辦法,叫做 async/await 因為 async/await 只是 promise 的另一種語法,背後一模一樣,所以繼續拿 jquery 當範例看看 原本的串接 ``` $.get(url, params).then((data) => { // do something with data to get params2 return $.get(url2, params2); }).then((data) => { // do something with data to get params3 return $.get(url3, params3); }).then((data) => { // do the final task with data }); ``` 可以用 async/await 改寫成 ``` const data1 = await $.get(url, params); // do something with data to get params2 const data2 = await $.get(url2, params2); // do something with data to get params3 const data3 = await $.get(url3, params3); // do the final task with data ``` 神奇吧?看起來跟一般的同步程式設計,幾乎一模一樣了! 這邊要知道的是,await 後面的內容,其實就是 `.then()` 裡面 `return` 回傳的內容 只是寫法不同,其實背後是完全一樣的東西! --- 這句話很重要,再看一次!未來只要有點迷惘,就用這句話再思考一次: 你每次只要看到 await,就要去想「現在是去剝開 promise 的 then 裡面,拿出最後回傳的內容!」 有點看不懂沒關係,就先跟著使用方式,照做即可! 工作上多用幾次之後,會逐漸抓到感覺! 就先跟著作業,試著使用看看 async/await 吧! --- 你可能會問:那 `async` 是什麼時候用? 在 JS 環境中,有些時候,可以直接寫 `await` 有些時候,會跳警告,要求必須要使用 `async` 關鍵字包裝過,才能使用 `await` 僅此而已,暫時分不清 `async` 關鍵字使用時機,沒關係,遇到警告錯誤,再補上就可以了 最簡單的做法,你就把整段程式碼,放進一個隨便命名的 `main` 函式裡面,加上 `async` 關鍵字,然後執行 main ``` const main = async () => { // move your code to here } main(); ``` 老話一句,工作上多用幾次之後,會逐漸抓到感覺! ## 課後作業 在前一課的作業中,你稍微體驗到 2015 年代,前端工程師使用的「Promise Chain 鏈接」寫法 在這一課的作業,我們將時間快轉到 2017 年代,體驗一下所謂 `async/await` 是什麼 --- jquery 有支援 promise 介面,所以當然可以直接用 async/await 原本的 `.then()` 寫法 ``` $.get(url, params).then(callback) ``` 可以改寫為 ``` const data = await $.get(url, params) ``` 請將上一課的作業,使用 async/await 改寫 寫完之後,你應該會看到多個 await 出現,並且整段程式碼看起來很像「一般程式語言中,同步程式設計」的寫法! 而且,完全沒有 callback function 的傳遞! 做出以上功能,你就完成這次的課程目標了! ### ⚠️特別注意事項:請耐心 debug!⚠️ 請注意,跟上一課一樣,由於本課簡化內容,沒有寫錯誤處理,錯誤訊息可能不會顯示! 請用 `console.log` 慢慢查看每行程式碼的執行結果,慢慢寫出這一課作業!

非同步 JS 訓練一:第2課 ── 認識 promise chain 鏈接

## 課程目標 - 認識 promise chain 鏈接 ## 課程內容 體驗過 callback hell 之後,工程師在 ES2015 提出了一個解決辦法,叫做 Promise 先不談細節,直接體驗使用方式看看! 繼續拿 jquery 為範例(因為 jquery 後來也有支援 promise 介面): 原本是把 callback function 當成參數傳遞 ``` $.get(url, params, (data) => { // do something with data }) ``` 現在改成串接呼叫 `.then()` 函式,然後把 callback function 放在這邊 ``` $.get(url, params).then((data) => { // do something with data }) ``` 乍看之下好像沒差,只是搬出來而已,其實真正的威力在於,連續多個非同步任務的時候 原本是越來越深層的 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 }); }); }); ``` 可以改寫成,在 `.then()` 中使用 `return` 來回傳 `新的 promise`,並且串接在一起 ``` $.get(url, params).then((data) => { // do something with data to get params2 return $.get(url2, params2); }).then((data) => { // do something with data to get params3 return $.get(url3, params3); }).then((data) => { // do the final task with data }); ``` 注意看!這段程式碼非常巧妙,不論執行多少個非同步任務,callback function 深度都只有一層! 大幅改善了 callback hell 的問題! 有點看不懂沒關係,就先跟著使用方式,照做即可! 工作上多用幾次之後,會逐漸抓到感覺! 就先跟著作業,試著使用看看 promise 吧! ## 課後作業 在前一課的作業中,你稍微體驗到 2000 年代,前端工程師面對的 callback hell 在這一課的作業,我們將時間快轉到 2015 年代,體驗一下所謂「Promise Chain 鏈接」是什麼 --- jquery 除了一開始的寫法之外 ``` $.get(url, params, callback) ``` 也有支援 promise 介面 ``` $.get(url, params).then(callback) ``` 請將上一課的作業,使用 promise chain 改寫 寫完之後,你應該會看到多個 `.then()` 串接在一起,不再出現多層深度的巢狀 callback 傳遞了! 做出以上功能,你就完成這次的課程目標了! ### ⚠️特別注意事項:請耐心 debug!⚠️ 請注意,由於使用 promise 介面,一般來說要同時寫「錯誤處理」的部份 這一課因為略過這部份沒寫,程式碼出錯的話,在「瀏覽器的開發者工具 console」裡面,可能不會顯示錯誤訊息!這會讓除錯難度增加!會比較難寫,這不是常態!是本課簡化內容的結果! 請用 `console.log` 慢慢查看每行程式碼的執行結果,慢慢寫出這一課作業!

非同步 JS 訓練一:第1課 ── 認識 callback hell

## 課程目標 - 認識 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 的感覺! 做出以上功能,你就完成這次的課程目標了!