Exploring Your First Async Sequences
Introduction to Async Sequences
Exploring Your First Async Sequences
Photo by Aziz Acharki on Unsplash
Async Sequences
- In Swift, sequences allow iteration over a collection of values, such as arrays or dictionaries, using a
forloop. - An async sequence (
AsyncSequence) extends this concept for asynchronous operations, where not all values in the sequence are available immediately. - Async sequences are ideal for streaming data, like reading lines from a file or receiving chunks of data over a network.
Sync vs. Async Loop
Synchronous Loop:
A typical synchronous loop processes all elements that are already available:
let myArray = [1, 2, 3]
for number in myArray {
print(number)
}
Asynchronous Loop:
An async loop processes elements as they become available, awaiting new data:
for try await line in csvURL.lines {
print(line)
}
- The loop suspends execution until the next value is available.
Practical Example: Reading a CSV File
Scenario:
You need to read and process a large CSV file line by line, where:
- Each line represents a record (e.g., a car’s details).
- Lines arrive asynchronously, such as over a network.
Basic Synchronous Parsing:
let csvData = try Data(contentsOf: url)
let csvString = String(data: csvData, encoding: .utf8)
let csvLines = csvString?.components(separatedBy: "\n") ?? []
for line in csvLines {
let components = line.components(separatedBy: ",")
guard components.count == 4 else { continue }
let car = Car(year: components[0], make: components[1], model: components[2], body_styles: components[3])
cars.append(car)
}
print(cars)
Problems with Synchronous Parsing:
Memory Usage:
- The entire file is loaded into memory before processing.
- Inefficient for large files.
Blocking:
- The main thread is blocked while reading and processing the file.
Network Inefficiency:
- When fetching from a URL, we wait for the entire file to download before starting any processing.
Using Async Sequences
Parsing Lines Asynchronously:
With AsyncSequence, you can process lines as they are received:
var cars = [Car]()
for try await line in csvURL.lines {
let components = line.components(separatedBy: ",")
guard components.count == 4 else { continue }
let car = Car(year: components[0], make: components[1], model: components[2], body_styles: components[3])
cars.append(car)
}
print(cars)
Key Difference:
- The
linesproperty onURLreturns anAsyncSequence. - Each line is fetched and processed as soon as it is available, minimizing memory usage and improving efficiency.
Control Flow in Async Loops
Async loops work like regular loops:
**break**: Exit the loop early.**continue**: Skip the current iteration.- Error Handling: Handle errors with
do-catchblocks.
Example:
do {
for try await line in csvURL.lines {
guard !line.isEmpty else { continue }
print(line)
}
} catch {
print("Failed to process lines:", error)
}
Parallelizing Async Loops
Sequential Execution:
By default, async loops run sequentially:
for try await line in csvURLPartOne.lines {
// Process part one
}
for try await line in csvURLPartTwo.lines {
// Process part two
}
- The second loop starts only after the first completes.
- Async sequences behave like regular loops in terms of execution order
Running Loops in Parallel:
To run loops in parallel, use separate Tasks:
Task {
for try await line in csvURLPartOne.lines {
print("Part one:", line)
}
}
Task {
for try await line in csvURLPartTwo.lines {
print("Part two:", line)
}
}
- Limitations: Without additional handling, it’s unclear when both tasks complete.
While this works to run code in parallel, it does prevent us from knowing when both tasks are completed in a nice way. We can fix this by assigning these two tasks to their own variables and awaiting their values:
Awaiting Multiple Tasks:
Combine tasks for structured concurrency:
Task {
let task1 = Task {
for try await _ in csvURLPartOne.lines {
print("Part one processing...")
}
}
let task2 = Task {
for try await _ in csvURLPartTwo.lines {
print("Part two processing...")
}
}
try await (task1.value, task2.value)
print("Both parts processed")
}
Using AsyncSequence Transformations
Async sequences support functional transformations, similar to synchronous sequences. For example:
Mapping Values:
let sequence = csvURL.lines.map { line -> Car in
let components = line.components(separatedBy: ",")
guard components.count == 4 else {
return Car(year: "", make: "", model: "", body_styles: "")
}
return Car(year: components[0], make: components[1], model: components[2], body_styles: components[3])
}
for try await car in sequence {
cars.append(car)
}
How It Works:
- Each line is transformed into a
Carobject as it is received. - The transformed
AsyncSequenceemitsCarobjects instead of raw lines.
Other Operations:
**filter**: Skip elements that don’t meet a condition.**flatMap**: Transform elements into sequences and flatten them.
Handling Errors in Async Sequences
Errors in async sequences are handled like errors in functions:
do {
for try await line in csvURL.lines {
print(line)
}
} catch {
print("Error:", error)
}
- If an error occurs, the loop ends, and control passes to the
catchblock.
Key Takeaways
Async Sequences vs. Sequences:
- Sequence: Processes all values that are already available.
- AsyncSequence: Processes values as they become available asynchronously.
Advantages of Async Sequences:
- Efficient memory usage by processing data incrementally.
- Useful for streaming data (e.g., reading files, network responses).
Transformations:
- Use
map,filter, and similar operations to process async sequences.
Parallel Execution:
- Async loops execute sequentially unless explicitly parallelized with tasks.
Structured Concurrency:
- Use
TaskGrouporasync letfor cleaner parallel execution (discussed further in later chapters).
By leveraging async sequences, you can write efficient, readable, and concurrent Swift code for scenarios involving streaming data.
메타데이터
- post_id
- 27873e66f303
- slug
- exploring-your-first-async-sequences-27873e66f303
- url
- https://medium.com/@abdulahd1996/exploring-your-first-async-sequences-27873e66f303
- canonical_url
- https://medium.com/@abdulahd1996/exploring-your-first-async-sequences-27873e66f303
- author_url
- https://medium.com/@abdulahd1996
- status
- ok
- fetched_at
- 2026-06-21 19:25:17