跳至主要內容

Workflow.foreach()

.foreach() 方法會建立迴圈,針對陣列中的每個項目執行步驟。它一律會回傳包含每次迭代輸出的陣列,並保留原始順序。

使用範例
「使用範例」的直接連結

workflow.foreach(step1, { concurrency: 2 })

參數
「參數」的直接連結

step:

Step
要在迴圈中執行的步驟執行個體。前一步驟必須回傳陣列型別。

opts?:

object
迴圈的選用設定。concurrency 選項控制可平行執行的迭代數量(預設:1)
number

回傳值
「回傳值」的直接連結

workflow:

Workflow
可供方法連結使用的 Workflow 執行個體。輸出型別是由步驟輸出型別組成的陣列。

行為
「行為」的直接連結

執行與等待
「執行與等待」的直接連結

.foreach() 方法會先處理所有項目,再執行下一個步驟。無論並行設定為何,.foreach() 後面的步驟都只會在每次迭代完成後執行。使用 concurrency: 1(預設值)時,項目會依序處理。使用較高的並行值時,項目會以批次平行處理,但下一個步驟仍會等待所有批次完成。

如果每個項目都需要執行多項操作,請使用巢狀 Workflow 作為步驟。這能將每個項目的所有操作集中在一起,也比串接多個 .foreach() 呼叫更清楚。範例請參閱 foreach 中的巢狀 Workflow

輸出結構
「輸出結構」的直接連結

.foreach() 一律會輸出陣列。輸出陣列中的每個元素,都對應至處理輸入陣列中相同索引元素的結果。

// Input: [{ value: 1 }, { value: 2 }, { value: 3 }]
// Step adds 10 to each value
// Output: [{ value: 11 }, { value: 12 }, { value: 13 }]

.foreach() 後使用 .then()
「using-then-after-foreach」的直接連結

.foreach() 後串接 .then() 時,下一個步驟會收到整個輸出陣列作為輸入。你可以彙總所有結果,或一起處理這些結果。

workflow
.foreach(processItemStep) // Output: array of processed items
.then(aggregateStep) // Input: the entire array
.commit()

.foreach() 後使用 .map()
「using-map-after-foreach」的直接連結

將陣列輸出傳給下一個步驟之前,可使用 .map() 進行轉換:

workflow
.foreach(processItemStep)
.map(async ({ inputData }) => ({
total: inputData.reduce((sum, item) => sum + item.value, 0),
count: inputData.length,
}))
.then(nextStep)
.commit()

串接多個 .foreach() 呼叫
「chaining-multiple-foreach-calls」的直接連結

串接 .foreach() 呼叫時,每個呼叫都會處理前一步驟產生的陣列:

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() 將其攤平:

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 完成,就能即時追蹤進度。

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<string, any>
迭代的輸出(iterationStatus 為 'success' 時提供)

繼續單次迭代
「繼續單次迭代」的直接連結

.foreach() 內的步驟暫停時,每次迭代都會個別暫停。將 forEachIndex 傳給 run.resume(),即可用各自的 resumeData 一次繼續一個迭代。省略 forEachIndex 則會使用相同資料,繼續所有已暫停的迭代。

await run.resume({
step: 'approve',
resumeData: { ok: true },
forEachIndex: 1,
})