嗨,大家今天過得好嗎?歡迎來到鐵人賽 Day 23。
昨天我們完成了歷史紀錄的雙向資料流,我們的「AI 硬體推薦 App」MVP 已經成型了。如果你都在本地端順順地測,感覺一切都很美好。
但現實世界是殘酷的。還記得我們在 Day 15 串接的那個「免費外部匯率 API」嗎?如果今天那個 API 的伺服器掛了,或是 OpenAI 的 API 突然大塞車 Timeout,會發生什麼事?
預設情況下,只要 n8n 裡面的任何一個節點噴錯,整個工作流就會當場中斷 (Crash)。後面的 AI 節點不會執行,最後的 Webhook 也不會回傳資料,你的 iOS App 就會一直傻傻轉圈圈,直到 30 秒後噴出 Timeout 錯誤。
身為全端工程師,我們不能允許系統這麼脆弱。今天,我們要來幫 n8n 工作流穿上防彈背心:實作 Fallback (備援機制) 與 Error Trigger (全域錯誤捕捉)。
以我們 Day 15 的「HTTP Request 匯率節點」為例。匯率雖然重要,但它不應該是阻礙 AI 配單的致命因素。如果抓不到最新匯率,大不了我們就用一個「預設匯率」來算就好,不應該讓整個系統死掉。
這在系統設計上稱為 Fallback(降級備援)。
On Error 的選項,把它從預設的 Stop Workflow 改為 Continue On Fail (失敗時繼續執行)。現在,就算外部 API 掛了,n8n 依然會往下一步走。但問題來了:如果有抓到資料,Output 會有 $json.rates.TWD;如果失敗了,Output 會變成一個包含錯誤訊息的 JSON,裡面根本沒有 rates,接下來的節點如果直接去讀取,還是會報錯!
||) 處理預設值我們要在後面接一個 Edit Fields 節點來「清理」這個變數。
在設定匯率變數時,請利用 JavaScript 的短路求值 (Short-circuit evaluation) 特性,這樣寫你的 Expression:
{{ $json.rates?.TWD || 32.5 }}
這句短短的語法威力無窮:
? (Optional Chaining):如果 rates 不存在,不會當機,只會回傳 undefined。|| (邏輯 OR):如果前面抓不到匯率 (undefined),就自動採用後面的預設值 32.5。就這麼簡單!我們成功在不寫 try-catch 的情況下,完美實作了商業級別的 Fallback 機制。即使外部服務大當機,你的 AI App 依然能生龍活虎地產出菜單。
有些節點的失敗是不能被 Fallback 的。例如:PostgreSQL 資料庫掛了,或是 OpenAI API Key 沒錢了。這種屬於「致命錯誤」,我們必須讓工作流停止,但同時我們要:
這時候,我們需要建立一個專門處理災難的「救護車工作流」。
Error Trigger 節點作為起點。這個節點沒有網址,它的作用是「只要 n8n 裡面的任何其他工作流發生了無法挽救的錯誤,這個節點就會被觸發」。execution.workflow.name (哪支工作流掛了)execution.error.message (具體的報錯訊息)系統警報
你的 AI 菜單系統掛了!
發生在:{{ $json.execution.workflow.name }}
錯誤原因:{{ $json.execution.error.message }}
如果你希望在發生致命錯誤時,還能用 Respond to Webhook 回傳 { "error": "伺服器維護中" } 給 iOS App,這在 Error Trigger 跨工作流的情況下是比較難做到的(因為 HTTP 連線會在原工作流中斷時關閉)。
實務上,我們會仰賴昨天 Day 20 寫在 SwiftUI 裡的 APIService Timeout 機制與 Catch 區塊,讓前端在等不到回應時,主動彈出友善的錯誤視窗。後端的 Error Trigger 則專心負責系統警報與工程師通知。
今天我們補齊了後端最後一塊、也是最常被忽略的拼圖:錯誤處理與強韌性設計。
透過 Continue On Fail 結合 || 預設值,我們馴服了不穩定的外部 API;透過 Error Trigger,我們建立了一套自動化的災難通報系統。
我們的專案在本地端(Localhost)已經強大無比、堅不可摧了。但只要你把電腦關掉,這個 App 就成了廢鐵。
明天,這場鐵人賽將邁入最後的終局之戰:部署 (Deployment)!
我們要離開 Localhost 的舒適圈,把 n8n 引擎與 PostgreSQL 資料庫正式搬上雲端伺服器 (VPS),讓全世界的玩家都能下載並使用你的 AI 硬體推薦 App!
我們 Day 24 見!