
當你的 n8n 工作流 (Workflow) 逐漸變得複雜,你肯定會遇到一個令人困惑的神秘事件:為什麼流程前面的資料,跑到後面就不見了?
情境是這樣的:你的流程由一個 Webhook
節點觸發,接收到了一筆包含客戶 ID 和姓名的新用戶資料。接著,你用這個客戶 ID 去呼叫一個 HTTP Request
節點,查詢該客戶的詳細訂單歷史。然後,你想在最後的 Send Email
節點中,同時使用來自 Webhook 的「客戶姓名」和來自 API 的「訂單歷史」來寄出一封個人化的信件。
但當你設定 Email 內容時,卻驚訝地發現,變數選擇器裡只剩下 HTTP Request
節點回傳的訂單資料,「客戶姓名」彷彿人間蒸發了。這個「資料消失」的問題,正是區分 n8n 新手與專家的關鍵門檻,而解開這個謎題的鑰匙,就在於理解 n8n 的兩種進階資料傳遞觀念:Static Data 與 Passthrough。
這篇文章將為你徹底解惑。我們將深入 n8n 資料流的底層邏輯,解釋為何資料會「消失」,並手把手教你如何利用 Merge
節點等工具,完美實現資料的「Passthrough (傳遞)」,讓你能夠像專家一樣,隨心所欲地在工作流的任何節點,存取任何你需要的歷史資料。
你是否也遇過?n8n 工作流中「資料消失」的神秘事件
在我們進入解決方案前,必須先深刻理解問題的根源。這個問題的核心,來自於 n8n 一個非常重要的預設行為。
認識 n8n 的預設行為:後浪推前浪的「資料取代」模型
在一個標準的 n8n 線性流程 A -> B -> C
中,資料的傳遞方式如下:
- 節點 A 執行完畢,產出
Output A
。 Output A
成為節點 B 的Input
。- 節點 B 根據
Input
執行自己的任務(例如呼叫 API),然後產出一個全新的Output B
。 Output B
成為節點 C 的Input
。
請注意關鍵的第三步:節點 B 的輸出,會完全「取代」掉節點 A 的輸出,成為下一棒的輸入。 節點 A 的資料並不是「消失」了,而是在 B 這一站被「換掉」了。這就是為什麼在我們開頭的例子中,Send Email
節點(節點 C)只能看到 HTTP Request
節點(節點 B)的資料,而看不到 Webhook
節點(節點 A)的資料。
解決方案一:使用 Merge
節點實現智慧資料「Passthrough (傳遞)」
那麼,該如何讓節點 A 的資料能夠「穿越」節點 B,和節點 B 的新資料一起抵達節點 C 呢?答案就是使用我們的好朋友:Merge
節點。
Merge
節點是實現資料 Passthrough 最標準、也最推薦的方式。它的作用是將兩個(或多個)不同的輸入源,根據規則合併成一個輸出。
「Passthrough」的設計模式
這個模式的架構非常經典:
- 在你的主流程中,當你需要從 A 節點的資料去 B 節點獲取新資料時,讓流程在這裡「分岔」。
- 一條路徑直接從 A 連到
Merge
節點的Input 1
。這條路徑就是「Passthrough 通道」,負責將原始資料安全地送達匯流點。 - 另一條路徑從 A 連到 B,再將 B 的輸出連到
Merge
節點的Input 2
。這條路徑是「資料獲取通道」。 - 在
Merge
節點中,設定合併規則,將兩條路徑的資料重新組合在一起。
Merge
節點的合併模式選擇
在 Merge
節點中,通常我們會使用 Merge by Index
或 Merge by Key
來實現 Passthrough:
Merge by Index
(按順序合併): 這是最簡單的 Passthrough 方式。由於 n8n 的迴圈特性,兩條分支的資料 Item 順序通常會是一致的。Merge by Index
會將 Input 1 的第一筆資料和 Input 2 的第一筆資料合併,第二筆和第二筆合併,依此類推。在大多數簡單的 Passthrough 情境下,這是最快的方法。Merge by Key
(按鍵值合併): 這是更穩健、更可靠的方式。你可以在 A 節點的資料和 B 節點的資料中,找到一個共通的欄位(例如customer_id
),並以此作為合併的「鑰匙」,確保資料絕對不會錯配。

解決方案二:手動管理 Static Data
,精準控制你的資料流
另一種思維是,不要依賴 Passthrough,而是在每一個步驟中,「手動」將你需要保留的歷史資料(我們稱之為 Static Data
)一代一代地傳下去。
這個方法通常在 Code
節點中比較常用,或者在一些只需要保留一兩個關鍵欄位的簡單情境。
手動傳遞的設計模式
- 情境: 你只需要保留 Webhook 傳來的
customer_name
。 - 操作步驟:
- 在
HTTP Request
節點之後,接上一個Set
節點。 HTTP Request
節點的輸出是新的訂單資料。- 在
Set
節點中,新增一個欄位,Name
設為customer_name
。 Value
使用 Expression,但這次我們要回頭去抓Webhook
節點的資料:{{ $node["Webhook"].json.body.customer_name }}
。
- 在
優缺點分析:
- 優點: 邏輯相對簡單,不需要分岔再合併,流程保持線性。
- 缺點: 如果要保留的欄位很多,
Set
節點會變得非常臃腫。同時,你需要在每個可能「覆蓋」資料的節點後都做一次這個動作,比較繁瑣。
結論: 對於絕大多數情境,使用 Merge
節點的 Passthrough 模式是更清晰、更具擴展性的最佳實踐。
實戰演練:Webhook 觸發後,如何保留原始資料並串接 API?
讓我們來完整地解決文章開頭的那個問題。
- 目標: Webhook 收到
{"name": "陳先生", "id": "C001"}
-> 用id
查詢 API 得到{"order_count": 5}
-> 發送 Email 內容包含「陳先生,您目前共有 5 筆訂單。」
步驟一:建立工作流骨架與分岔
- 建立
Webhook
節點作為觸發器。 - 在
Webhook
之後,將流程分岔:- 路徑一 (Passthrough): 直接從
Webhook
拉一條線,準備接到Merge
節點。 - 路徑二 (資料處理): 從
Webhook
拉另一條線到HTTP Request
節點。
- 路徑一 (Passthrough): 直接從
步驟二:設定資料處理路徑
- 設定
HTTP Request
節點。 URL
中使用 Expression 來代入客戶 ID:https://api.mycrm.com/orders?customer_id={{ $json.body.id }}
。- 執行一次,確保這個節點能成功抓回訂單數量的資料。
步驟三:設定 Merge
節點
- 將 路徑一 (Webhook 的輸出) 連接到
Merge
節點的Input 1
。 - 將 路徑二 (
HTTP Request
的輸出) 連接到Merge
節點的Input 2
。 - 設定
Merge
節點:- Mode: 選擇
Merge by Index
(因為此情境中只有一筆資料,順序是固定的)。 - Join: 選擇
Inner Join
。
- Mode: 選擇
步驟四:設定最終動作
- 將
Merge
節點的輸出,連接到Send Email
節點。 - 現在,點開
Send Email
節點的 Expression 編輯器,你會發現來自Webhook
的name
和來自HTTP Request
的order_count
都同時存在於$json
變數中! - 你可以輕鬆地寫出郵件內容:
{{ $json.name }},您目前共有 {{ $json.order_count }} 筆訂單。
你就成功地實現了資料的 Passthrough,解決了資料消失的問題!
最佳實踐:何時該用 Merge?何時該手動處理?
- 優先使用
Merge
節點: 當你需要保留多個原始欄位,或是整個原始資料物件時,Merge
節點的 Passthrough 模式是最乾淨、最標準的做法。它讓你的資料來源和處理邏輯分離,非常清晰。 - 考慮手動處理 (Set 節點): 當你自始至終只需要保留一兩個關鍵的 ID 或標籤,且流程相對簡單時,用
Set
節點手動將它們一代代傳下去,可以讓流程保持線性,也是一個可行的選擇。 - Code 節點中的考量: 在
Code
節點中,你擁有完全的控制權。你可以透過const originalData = $item("Webhook").json;
這樣的語法,在程式碼中隨時回頭抓取任何歷史節點的資料,並與當前資料進行任意組合。

結語
理解 n8n「資料取代」的預設模型,並學會運用 Passthrough 技巧來保留你需要的 Static Data
,是將你的 n8n 技能從入門提升至進階的核心觀念。這不僅僅是一個技術操作,更是一種流程設計的思維轉變。
下次當你發現資料在工作流中途不翼而飛時,請不要再感到困惑。記住今天學到的 Merge
節點 Passthrough 模式,透過優雅的「分岔-匯流」架構,你就能確保任何你需要的資料,都能安全、準確地抵達流程中的任何一個角落。