Alpha Camp 學期 2-3 結業心得
隨著時間的推移,在學習上總是會碰到各種不同的狀況,而這些狀況也提供我不同的學習感受。這篇著重於紀錄自己遇到、找出並排除問題的過程。
要解決問題,必須先正確的找出問題發生原因。
緣起:為短網址產生器加上重複檢查機制
一如上學期結束時對自己許的願,這學期在寫作業的同時會盡可能地做些優化挑戰,然後不可避免的進入無窮卡關迴圈……
近期卡了最久的就是短網址產生器了!! 作業的要求其實很簡單,只要可以產生英文字母或數字的隨機亂碼來當短網址即可。但是! 我突然想到:「萬一真的產生了相同的亂碼怎麼辦?」。依照我當下的執行邏輯,產生亂碼之後就馬上把它和原始網址加入互相對照的 index ,在沒有檢查的情況下,兩組原始網址導向同一個短網址也不是不可能發生。
於是,我決定了優化方向:「在亂數產生器 return 結果之前加上檢查機制」,只要發現相同亂碼就重新執行一次亂碼產生流程。然後……在這個優化過程被卡了整整 2 天 🤣
嘗試失敗1:同步與非同步
先來備註一下:這次用來存放 UrlIndex 資料的是 MongoDB。
原本的寫法如下(只放有問題部分):
1 |
|
在我的預想中, generator()
負責產生獨一無二的短網址,而 UrlIndex.create()
把取得的短網址拿去建立 index 。但是,看似沒問題的邏輯跳錯誤了! 好在目前遇到的大部分錯誤訊息都能正確敘述出問題的原因,它告訴我 shortenUrl 的值 undefined
。於是我去查查賦值 undefined
的原因,發現在我寫的流程裡最有可能的原因是:「若變數沒有提供初始值,則預設為 undefined
」。但不對啊~我不是有告訴 UrlIndex.create()
shortenUrl 的值從 generator()
取得嗎? 為什麼會 undefined
呢?
前幾天因緣際會接觸到「非同步」相關知識的我想起了前輩對非同步的評語:
實戰常常遇到問題,一研究發現,怎麼又是你!
檢查了一下目前進度,確實啊~ UrlIndex.create()
和 UrlIndex.findOne()
都是非同步語法,如果沒有處理好,根本無法控制完成的先後順序。於是,再度開始了 google 旅程,發現目前對於非同步執行順序最常使用兩種方式:
- async/await
- Promise.then()
因為對 async/await
值的傳遞方式還不太熟悉,因此決定先用 Promise.then()
的方式。 .then
的前面必須是個 Promise 物件,但我目前 return 的是亂碼「值」。幸好查到的資料告訴我, mongoose 5.0 開始就內建 Promise 語法,所以我可以把整個 UrlIndex.findOne()
包成 Promise 物件。最後,我把整個檢驗是否重複的過程直接 return ,順利解決了執行順序問題。
1 |
|
嘗試失敗2:mongoose 語法 return 值
接著,我想把產生的短網址結果呈現給使用者:
1 |
|
這時候又跳錯誤了! 根據錯誤訊息查詢,發現是 handlebars 因為安全性問題,只接受乾淨的物件資料,通常可以用 .lean()
解決。把 urlData
印出來,看看到底取到什麼值? 嗯?? _id
裡面那個 new 是什麼? 看起來確定是回傳值的問題。
於是我加上了 .lean()
,但它又報錯了!
1 |
|
測試後發現:如果是已建立 index 的網址就沒問題;反之,如果是新建的就會報錯。那就表示兩者拿到的資料不一樣。仔細查閱了 mongoose 官方文件, UrlIndex.findOne()
回傳 Query、 UrlIndex.create()
回傳 Promise 物件……好吧! 接下來的問題就是如何取 UrlIndex.create()
的「值」?
在各種變換關鍵字後,終於在 stack overflow 找到救世主,可以用 toObject()
進行資料轉換。
1 |
|
大功告成! 一切終於都如我預期的運作了!!
成品程式碼: 在這裡。
心得分享
寫出來真的很有成就感啊!! 除了這個作業優化外,其實前面的作業也有經過類似的優化煎熬過程。總結起來解決問題的方法分幾個部分:
- 預防 – 仔細閱讀使用工具的官方文件、了解它的使用方法,正確的使用工具可以排除很多可能發生的問題。
- 找出問題 – 知道問題發生原因才是解決的最快方法。就像前面分享的問題二,看起來是 handlebars 接受的資料類型問題,實際上是 mongoose 回傳值的原因。
- 查找資料 – 在找出正確問題的前提下,盡可能下對關鍵字可以找到更接近需求的內容。
不過沒有一次找到目標資料也沒關係,多多閱讀的過程中也能吸收各種知識,也許會在未來的某一天成為解決其他問題的關鍵!
文章內容如有錯誤,歡迎留言討論!
本 Blog 上的所有文章除特别聲明外,均採用 CC BY-SA 4.0 協議 ,轉載請註明出處!