> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-TW/llms.txt # Workflow\.foreach() `.foreach()` 方法會建立迴圈,針對陣列中的每個項目執行步驟。它一律會回傳包含每次迭代輸出的陣列,並保留原始順序。 ## 使用範例 ```typescript workflow.foreach(step1, { concurrency: 2 }) ``` ## 參數 **step** (`Step`): 要在迴圈中執行的步驟執行個體。前一步驟必須回傳陣列型別。 **opts** (`object`): 迴圈的選用設定。concurrency 選項控制可平行執行的迭代數量(預設:1) ## 回傳值 **workflow** (`Workflow`): 可供方法連結使用的 Workflow 執行個體。輸出型別是由步驟輸出型別組成的陣列。 ## 行為 ### 執行與等待 `.foreach()` 方法會先處理所有項目,再執行下一個步驟。無論並行設定為何,`.foreach()` 後面的步驟都只會在每次迭代完成後執行。使用 `concurrency: 1`(預設值)時,項目會依序處理。使用較高的並行值時,項目會以批次平行處理,但下一個步驟仍會等待所有批次完成。 如果每個項目都需要執行多項操作,請使用巢狀 Workflow 作為步驟。這能將每個項目的所有操作集中在一起,也比串接多個 `.foreach()` 呼叫更清楚。範例請參閱 [foreach 中的巢狀 Workflow](https://mastra.zisheng.pro/zh-TW/docs/workflows/control-flow)。 ### 輸出結構 `.foreach()` 一律會輸出陣列。輸出陣列中的每個元素,都對應至處理輸入陣列中相同索引元素的結果。 ```typescript // Input: [{ value: 1 }, { value: 2 }, { value: 3 }] // Step adds 10 to each value // Output: [{ value: 11 }, { value: 12 }, { value: 13 }] ``` ### 在 `.foreach()` 後使用 `.then()` 在 `.foreach()` 後串接 `.then()` 時,下一個步驟會收到整個輸出陣列作為輸入。你可以彙總所有結果,或一起處理這些結果。 ```typescript workflow .foreach(processItemStep) // Output: array of processed items .then(aggregateStep) // Input: the entire array .commit() ``` ### 在 `.foreach()` 後使用 `.map()` 將陣列輸出傳給下一個步驟之前,可使用 `.map()` 進行轉換: ```typescript workflow .foreach(processItemStep) .map(async ({ inputData }) => ({ total: inputData.reduce((sum, item) => sum + item.value, 0), count: inputData.length, })) .then(nextStep) .commit() ``` ### 串接多個 `.foreach()` 呼叫 串接 `.foreach()` 呼叫時,每個呼叫都會處理前一步驟產生的陣列: ```typescript workflow .foreach(stepA) // If input is [a, b, c], output is [A, B, C] .foreach(stepB) // Operates on [A, B, C], output is [A', B', C'] .commit() ``` 如果 `.foreach()` 內的步驟回傳陣列,輸出就會成為陣列的陣列。請搭配 `.flat()` 使用 `.map()` 將其攤平: ```typescript workflow .foreach(chunkStep) // Output: [[chunk1, chunk2], [chunk3, chunk4]] .map(async ({ inputData }) => inputData.flat()) // Output: [chunk1, chunk2, chunk3, chunk4] .foreach(embedStep) .commit() ``` ### 串流期間的進度事件 使用 `run.stream()` 時,foreach 步驟會在每次迭代完成後發出 `workflow-step-progress` 事件。你不必等待整個 foreach 完成,就能即時追蹤進度。 ```typescript const run = await workflow.createRun() const stream = run.stream({ inputData }) for await (const chunk of stream) { if (chunk.type === 'workflow-step-progress') { console.log(`${chunk.payload.completedCount}/${chunk.payload.totalCount}`) // e.g. "1/3", "2/3", "3/3" } } ``` 每個進度事件的 payload 都包含: **id** (`string`): foreach 步驟的步驟 ID **completedCount** (`number`): 目前已完成的迭代數量 **totalCount** (`number`): 迭代總數 **currentIndex** (`number`): 剛完成之迭代的索引 **iterationStatus** (`'success' | 'failed' | 'suspended'`): 剛完成之迭代的狀態 **iterationOutput** (`Record`): 迭代的輸出(iterationStatus 為 'success' 時提供) ### 繼續單次迭代 `.foreach()` 內的步驟暫停時,每次迭代都會個別暫停。將 `forEachIndex` 傳給 [`run.resume()`](https://mastra.zisheng.pro/zh-TW/reference/workflows/run-methods/resume),即可用各自的 `resumeData` 一次繼續一個迭代。省略 `forEachIndex` 則會使用相同資料,繼續所有已暫停的迭代。 ```typescript await run.resume({ step: 'approve', resumeData: { ok: true }, forEachIndex: 1, }) ``` ## 相關內容 - [使用 foreach 建立迴圈](https://mastra.zisheng.pro/zh-TW/docs/workflows/control-flow) - [run.resume()](https://mastra.zisheng.pro/zh-TW/reference/workflows/run-methods/resume)