Swift PromiseKit:是否存在when()的顺序执行等效方法?
Hey there! I see you're trying to get sequential execution working with PromiseKit, and ran into issues with your recursive approach—let's sort this out.
What's Wrong With Your Current Code?
Your recursive function has two key issues causing the out-of-order execution and "Promise deallocated" errors:
- Unbound Outer Promise: The outer
Promise<Void>you create doesn't properly tie into the recursive promise chain. You start the first promise but never link its completion to the outer promise'sfulfilorrejectcalls. This means the outer promise might be deallocated before the chain finishes. - Mutable Array Timing: You modify the
mutablePromisesarray inside thethenclosure, which runs after the first promise completes. Since you pass a copy ofmutablePromisesto the recursive call, the ordering logic gets tangled up.
The Better Approach: Use reduce for Sequential Chaining
PromiseKit plays beautifully with Swift's reduce function to build a clean sequential promise chain. This avoids recursion pitfalls and ensures proper memory management:
static func executeSequentially(promises: [Promise<Void>]) -> Promise<Void> { // Start with an immediately fulfilled promise to kick off the chain return promises.reduce(Promise.value(())) { previousPromise, nextPromise in previousPromise.then { // Wait for the previous promise to finish, then run the next one nextPromise } } }
How This Works
- We start with
Promise.value(())—a fulfilled promise—to initialize the chain. - For each promise in the array, we link it to the end of the previous promise using
then. This guarantees each promise only starts executing after the one before it completes successfully. - If any promise in the chain rejects, the entire chain rejects immediately, which is the expected behavior for sequential execution.
Fixing Your Recursive Implementation (If You Prefer Recursion)
If you want to stick with a recursive approach, here's how to fix it by properly binding the recursive chain to the returned promise:
static func executeSequentially(promises: [Promise<Void>]) -> Promise<Void> { guard !promises.isEmpty else { return Promise.value(()) // Empty array = immediately fulfilled } let firstPromise = promises.first! let remainingPromises = Array(promises.dropFirst()) return firstPromise.then { // After the first completes, run the rest sequentially executeSequentially(promises: remainingPromises) } }
This version eliminates the manual outer Promise creation (which caused the deallocation issue) and directly returns the chained promise. By splitting the array into the first element and remaining elements upfront, we avoid mutable array confusion.
Key Takeaways
- Avoid manual
Promisecreation unless absolutely necessary—let PromiseKit's built-in functions handle chaining and memory management. reduceis the idiomatic way to build sequential promise chains in Swift + PromiseKit.- When using recursion, ensure each step returns the chained promise instead of wrapping it in an unbound outer promise.
内容的提问来源于stack exchange,提问作者derf26

