Closures Vs. Combine Vs. Async Await
Introduction
There are three methods of asynchronous coding in Swift: Closures (i.e. completion handlers), Combine, and Async/Await.?
Closures are a fundamental feature of Swift that allow developers to define self-contained blocks of functionality, while Combine provides a modern way to handle asynchronous events and data streams. Async/Await is a new feature that makes it easier to write asynchronous code that looks and feels like synchronous code, improving the readability and maintainability of Swift code.
Asynchronous Coding Methods
Closures
In Swift programming, closures are a powerful and versatile feature that allow you to capture and store functionality for later use. A closure is a self-contained block of code that you can pass around and execute at a later time, similar to a function or method.
A common use case for closures is handling asynchronous operations, such as network requests or animations. Defining a closure that executes when the operation completes helps you to keep your code organized and avoid callback functions.
You can use closures in Swift in different ways:
Closures can capture and retain references to values outside of their own scope which allows you to define closures that can access and modify variables defined outside of their own function or method.?
Combine
Combine is a powerful framework that allows developers to handle asynchronous events and data streams in a more intuitive and functional way. The Combine framework provides a declarative way to define and manipulate data streams using a set of operators that can transform, filter, and combine data in various ways.
Key use cases for the Combine framework include:
The key building blocks of Combine are?publishers?and?subscribers. Publishers are objects that emit a stream of values over time, while subscribers consume these values and perform some action in response. Publishers can be transformed, combined, and filtered using various operators to create complex data pipelines.
In summary, the Combine framework provides a powerful way to handle asynchronous events and data streams in Swift programming.
Async/Await
Async/Await provides a more intuitive and concise way to write asynchronous code. With Async/Await, developers can write asynchronous code that looks and feels like synchronous code, which makes it easier to read, write, and maintain.
Previously, developers used callbacks or closures to handle the results of asynchronous operations which often lead to complex and difficult-to-read code, as well as potential issues with callback hell and race conditions.
With Async/Await, developers can use familiar keywords like Await and Async to write asynchronous code, which allows them to pause the execution of a function until a result is available, without blocking the main thread. This makes it easier to write code that is both asynchronous and easy to understand.
For example, this code uses Async/Await to perform a network request:
领英推荐
In the example, fetchUser() function is marked as Async, indicating that it is an asynchronous function. Inside the function, the await keyword is used to wait for the result of the network request, without blocking the main thread. The result is then returned as a User object.
Overall, Async/Await is a powerful new feature that makes it easier to write asynchronous code in Swift, while also improving readability and maintainability.
Comparison
Features
Note that while Closures and Combine are both used for handling asynchronous operations, they operate at different levels of abstraction. Closures are used for defining code blocks with captured values, whereas Combine is a reactive programming framework that provides a unified way to manage asynchronous data streams. Async/Await, on the other hand, is a language-level feature that simplifies the process of writing asynchronous code by allowing developers to write asynchronous code that looks and feels like synchronous code.
Side-By-Side Code Function Definition
The?Closure?example code is fairly complex and a developer would need to examine the entire code block to be certain of its operation.
In the?Combine?block, the code is slightly less complex. The addition of?.map,?.decode, and?.mapError?help make it more understandable.
In the?Async/Await?code block, not only is there less code, it is also easier to understand what the code does: Set the path, create the request, make the call, and send the data back.
The code is still doing all of the?“heavy lifting”?for asynchronous coding, but it doesn’t?LOOK?as though it is doing the heavy lifting.
Side-By-Side Function Usage
The comparison of the three approaches?really?becomes clear when you look at the synchronizing calls inside of the same function.
As you can see, the result of the first call (i.e. getting a list of food by name) must come back to complete the second call (i.e. getting a list of foods that have the same “category” as the initial result).
Managing the response from the initial call is rather difficult, especially if we need to obtain sensible information about an error when something does go wrong. That difficulty only increases when we become reliant not only on a successful response, but also rely on the data as a result of that second response to power the second request.
Resources
Combine
Async Await
This article was originally published as a part of the Propel Spring Quarterly Summit series on the InRhythm blog.
This newsletter was curated by InRhythm's Senior Technical Writer,?Mike Adams. Thoughts or questions? Sound off in the comments section below.
Angular Developer
10 个月Comparison doesn't do justice to Combine. Why would you catch smth that is realistically should be considered normal flow, i.e. empty search result. Anyway you can create observables for uncategorized and categorized results, latter subscribing to former, then use CombineLatest on them both or use them as published vars in viewmodel.
Technology Enthusiast in the 615
1 年Thank you for the great write up Mike Adams