{"id":55106,"date":"2022-07-01T13:57:13","date_gmt":"2022-07-01T08:27:13","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=55106"},"modified":"2022-07-06T11:33:13","modified_gmt":"2022-07-06T06:03:13","slug":"networking-layer-with-combine","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/networking-layer-with-combine\/","title":{"rendered":"Networking layer with Combine"},"content":{"rendered":"<p><b>What is Combine?<\/b><\/p>\n<p>The <b>Combine<\/b> Framework &#8211; A framework rolled back in 2019 that works on the fundament of Functional Reactive Programming (FRP) paradigm similar to RxSwift and ReactiveSwift. It is developed by Apple and can be seen as a 1st party alternative to RxSwift and ReactiveSwift.<\/p>\n<p>Let\u2019s read from the documentation:<\/p>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/combine\"><i>Customize handling of asynchronous events by combining event-processing operators.<\/i><\/a><\/p>\n<p>This article takes liberty assuming that we have the basic understanding of the three key moving pieces in Combine which are <b>publishers<\/b>, <b>operators<\/b>,\u00a0<b>subscribers,\u00a0<\/b>and how we can create a <b>Combine Pipeline<\/b>.<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/gist.github.com\/ankittlp\/f4a421963e94263e426263e413f70efd\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-55092 alignnone aligncenter\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-25-at-11.52.51-PM.png\" alt=\"Example of Combine Pipeline\" width=\"1364\" height=\"226\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-25-at-11.52.51-PM.png 1364w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-25-at-11.52.51-PM-300x50.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-25-at-11.52.51-PM-1024x170.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-25-at-11.52.51-PM-768x127.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-25-at-11.52.51-PM-624x103.png 624w\" sizes=\"(max-width: 1364px) 100vw, 1364px\" \/><\/a><a href=\"https:\/\/gist.github.com\/ankittlp\/f4a421963e94263e426263e413f70efd\">Example of Combine Pipeline<\/a><\/p>\n<p>In this post, we\u2019ll talk about the implementation of the networking layer using <b>Combine. <\/b>While in the implementation we will touch on some topics like <b>Protocols<\/b>, <b>Generics, Associative Protocols,\u00a0<\/b>and Of Course Combine\u2019s flavor of <b>URLSession<\/b><\/p>\n<p>Before we jump into writing the <b>Networking Layer using Combine, <\/b>let&#8217;s revisit the <b>\u201cCall back\u201d<\/b> type network layer we generally have been implementing in our code.<\/p>\n<p>In this networking layer, we have defined a few protocols that define our API abstraction. To highlight the <b>Combine\u2019s way of networking layer<\/b>, It will be more related if we refactor the <b>\u201cCall back\u201d<\/b> (closure) type network layer. On a refactoring adventure like this, it&#8217;s a good idea to start by changing the protocols first and update the implementations later.<\/p>\n<p><a href=\"https:\/\/gist.github.com\/ankittlp\/7fa8ba187933b448321e4fcf428a1603\">Link to CallBack Type Request Protocol<\/a><\/p>\n<p>Before we update the protocol let\u2019s spend some time understanding these Protocols and their purpose. As mentioned we\u2019ll brush up on a few advanced swift topics like <b>Protocols<\/b>, <b>Generics, and Associative Protocols.<\/b><\/p>\n<p>As we see in the code above there are many protocols, so do we really need them?? Well honestly no we don\u2019t but we should if we want our app and the API to be decoupled, which in turn will allow us to mock it easily for testing.<\/p>\n<p>Let me say it loud: <b>Protocols <\/b>are<b> AWESOME.<\/b><\/p>\n<p>Now let\u2019s analyze the protocols in detail:<\/p>\n<p><b>Request<\/b> :<\/p>\n<p><b>\/\/ An AssociatedType Protocol: Request type to be implemented by Concrete Requests<\/b><\/p>\n<p><a href=\"https:\/\/gist.github.com\/ankittlp\/7fa8ba187933b448321e4fcf428a1603\"><img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-55094\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.00.27-AM.png\" alt=\"\" width=\"2008\" height=\"592\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.00.27-AM.png 2008w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.00.27-AM-300x88.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.00.27-AM-1024x302.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.00.27-AM-768x226.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.00.27-AM-1536x453.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.00.27-AM-624x184.png 624w\" sizes=\"(max-width: 2008px) 100vw, 2008px\" \/><\/a><\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/gist.github.com\/ankittlp\/7fa8ba187933b448321e4fcf428a1603\"><span style=\"font-weight: 400;\">Link to CallBack Type Request Protocol<\/span><\/a><\/p>\n<p>This Request type is an associated Type Generic Protocol that defines two associated types to operate on.<\/p>\n<ol>\n<li><b>Response type <\/b>constrained to be decodable<\/li>\n<li><b>ResponseParser<\/b> is constrained to be of <b>ResponseParserType<\/b> where ResponseParserType is another ATP over Response type. Also, We type constrain ResponseParser to be able to guarantee that Parser is for the correct Response type.<\/li>\n<li>We have defined a few required properties for the request.<\/li>\n<li>Next, we have an errorParser of <b>ErrorParserType <\/b>Protocol Type that allows the Implementing Request type to use a custom error parser over the default one.<\/li>\n<\/ol>\n<p>That very much describes the <b>Request Protocol<\/b> that will be used by our app code to declare every request type.<\/p>\n<p>But, this protocol remains as-in. It doesn\u2019t use the callback so we don\u2019t have to convert this to use combine.<\/p>\n<p>Next, <b>RequestExecutor :<\/b><\/p>\n<p>This protocol declares the abstraction for the request executor implementation. This will help us to switch over the API (Framework) making requests.<\/p>\n<div id=\"attachment_55095\" style=\"width: 1836px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/gist.github.com\/ankittlp\/7fa8ba187933b448321e4fcf428a1603\"><img aria-describedby=\"caption-attachment-55095\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-55095\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-12.40.15-AM.png\" alt=\"\" width=\"1826\" height=\"138\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-12.40.15-AM.png 1826w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-12.40.15-AM-300x23.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-12.40.15-AM-1024x77.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-12.40.15-AM-768x58.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-12.40.15-AM-1536x116.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-12.40.15-AM-624x47.png 624w\" sizes=\"(max-width: 1826px) 100vw, 1826px\" \/><\/a><p id=\"caption-attachment-55095\" class=\"wp-caption-text\"><a href=\"https:\/\/gist.github.com\/ankittlp\/7fa8ba187933b448321e4fcf428a1603\"><span style=\"font-weight: 400;\">Link to CallBack Type Request Protocol<\/span><\/a><\/p><\/div>\n<p>Mark the use of generic type but let me make this clear that it is just a Protocol with a function that accepts generic requests. It is an implementation of <b>type erasure<\/b> concept that allows the use of the Generic Protocol as type.<\/p>\n<p>And <b>This is not an ATP (associated type Protocol)<\/b><\/p>\n<p>That will pretty much make our Networking API. Let\u2019s just see the implementation of <strong>RequestExecutor.<\/strong><\/p>\n<div id=\"attachment_55096\" style=\"width: 1848px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/gist.github.com\/ankittlp\/b07024675266c70c0337c9f56bec05e2\"><img aria-describedby=\"caption-attachment-55096\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-55096\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.11.37-AM.png\" alt=\"\" width=\"1838\" height=\"1704\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.11.37-AM.png 1838w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.11.37-AM-300x278.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.11.37-AM-1024x949.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.11.37-AM-768x712.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.11.37-AM-1536x1424.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.11.37-AM-624x579.png 624w\" sizes=\"(max-width: 1838px) 100vw, 1838px\" \/><\/a><p id=\"caption-attachment-55096\" class=\"wp-caption-text\"><a href=\"https:\/\/gist.github.com\/ankittlp\/b07024675266c70c0337c9f56bec05e2\"><span style=\"font-weight: 400;\">Link to RequestExecutor Implementation<\/span><\/a><\/p><\/div>\n<p>The code is self-explanatory as it just implements the <b>RequestExecutor<\/b> protocol.<\/p>\n<p>The function <b>executeRequest<\/b> is where all the magic happens. It takes the request type and converts it to URLRequest through <b>RequestConvertible<\/b> to use it with the newly created dataTask. You will notice how conveniently the validations of using the right parser and response type are kept with <b>Request type<\/b> and the only job of the request executor is to make network calls.<\/p>\n<p>And that is what a scalable network layer will take to work.<\/p>\n<p>But wait, where is <b>Combine ?<\/b><\/p>\n<p>Yes, It is the time to start over and <b>Combine.<\/b><\/p>\n<p>We\u2019ll start by refactoring the <b>RequestExecutor<\/b> protocol, As it was the only protocol in our API abstraction that makes use of <b>Call back <\/b>(closures)<b>.<\/b><\/p>\n<div id=\"attachment_55097\" style=\"width: 1552px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/gist.github.com\/ankittlp\/5c5c8d7ac8ea3b7f37e01cb9c8800df7\"><img aria-describedby=\"caption-attachment-55097\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-55097\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.14.29-AM.png\" alt=\"\" width=\"1542\" height=\"130\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.14.29-AM.png 1542w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.14.29-AM-300x25.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.14.29-AM-1024x86.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.14.29-AM-768x65.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.14.29-AM-1536x129.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.14.29-AM-624x53.png 624w\" sizes=\"(max-width: 1542px) 100vw, 1542px\" \/><\/a><p id=\"caption-attachment-55097\" class=\"wp-caption-text\"><a href=\"https:\/\/gist.github.com\/ankittlp\/5c5c8d7ac8ea3b7f37e01cb9c8800df7\"><span style=\"font-weight: 400;\">Link to Combine&#8217;s Network layer Protocols<\/span><\/a><\/p><\/div>\n<p><a href=\"https:\/\/gist.github.com\/ankittlp\/5c5c8d7ac8ea3b7f37e01cb9c8800df7\">Link to Combine&#8217;s Network layer Protocols<\/a><\/p>\n<p>This is what <b>RequestExecutor<\/b> refactor is all it takes to be used for <b>Combine.\u00a0<\/b><\/p>\n<p>The changes:<\/p>\n<ol>\n<li>We removed the call back parameter instead there is a return type of <b>AnyPublisher<\/b> Generic over Request\u2019s response and Error.<\/li>\n<li>Refactoring also saw use of <b>Generic where clause<\/b> for constraining <b>R<\/b> type with <b>RequestConvertable<\/b>. but it&#8217;s just a syntactic change induced to brush up the use of <b>where clause.<\/b><\/li>\n<\/ol>\n<p>Note that there is use of <b>AnyPublisher<\/b> which is common in Combine with its own benefits. But Why not use the Publisher specifically available <b>URLSession.DataTaskPublisher&lt;T, Error&gt;<\/b> over DataTask. The reason for not using DataTaskPublisher or any other specific publisher is to not make our <b>executeRequest <\/b>function tightly coupled with the implementation. We\u2019ll talk more on <b>AnyPublisher<\/b> in a while.<\/p>\n<p>That is all with the refactoring part of Protocols, The next step is to refactor the actual implementation of these abstractions.<\/p>\n<p>Let\u2019s now see the simple use of <b>URLSession.DataTaskPublisher <\/b>for making Web api requests and then we\u2019ll add it to our Refactoring.<\/p>\n<p><b>Data task with Combine:<\/b><\/p>\n<div id=\"attachment_55098\" style=\"width: 1316px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-55098\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-55098\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.05.35-AM.png\" alt=\"\" width=\"1306\" height=\"246\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.05.35-AM.png 1306w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.05.35-AM-300x57.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.05.35-AM-1024x193.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.05.35-AM-768x145.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.05.35-AM-624x118.png 624w\" sizes=\"(max-width: 1306px) 100vw, 1306px\" \/><p id=\"caption-attachment-55098\" class=\"wp-caption-text\">Data task in Combine<\/p><\/div>\n<p>This pipeline defines the <b>urlSessionPublisher<\/b> and subscribe it using <b>sink <\/b>subscriber<b>. <\/b>That is the most basic form of combine\u2019s pipeline for DataTask.<\/p>\n<p>This does the job of making requests over the network and fetching us the data, url response objects. But using it in our implementation is still a long way.<\/p>\n<p>Let\u2019s evolve the current pipeline using some awesome<b> operators.<\/b><\/p>\n<div id=\"attachment_55099\" style=\"width: 1742px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/gist.github.com\/ankittlp\/aac9eb63f5cf6279a4ca3445a2c9d4e4\"><img aria-describedby=\"caption-attachment-55099\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-55099\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.09.10-AM.png\" alt=\"\" width=\"1732\" height=\"388\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.09.10-AM.png 1732w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.09.10-AM-300x67.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.09.10-AM-1024x229.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.09.10-AM-768x172.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.09.10-AM-1536x344.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.09.10-AM-624x140.png 624w\" sizes=\"(max-width: 1732px) 100vw, 1732px\" \/><\/a><p id=\"caption-attachment-55099\" class=\"wp-caption-text\"><a href=\"https:\/\/gist.github.com\/ankittlp\/aac9eb63f5cf6279a4ca3445a2c9d4e4\"><span style=\"font-weight: 400;\">Link to Network Subscription Stream with operators<\/span><\/a><\/p><\/div>\n<p>This is much evolved now, let\u2019s talk about these updates to our pipeline.<\/p>\n<ol>\n<li>We are using map operator to transform the output <b>(data: Data, response: URLResponse) <\/b>of urlSessionPublisher to data ignoring the response.<\/li>\n<li><b>decode<\/b> is used to load the data and attempt to parse it. <b>Decode<\/b> can throw an error itself if the decode fails. If it succeeds, the object passed down the pipeline will be the struct from the JSON data.<\/li>\n<li>In case of any error we handle it here using <b>replaceError<\/b>, as we don\u2019t want our pipeline (Subscription) to finish with failure.\u00a0 We may also use the <b>catch <\/b>operator instead of using replaceError. But it is to mind that even with <b>replaceError<\/b> or <b>catch<\/b> operator if there is an error in the stream, it will end up by finishing the pipeline.<\/li>\n<li>Using <b>eraseToAnyPublisher()<\/b> to expose an instance of <b>AnyPublisher<\/b> to the downstream subscriber, rather than this publisher\u2019s actual type. This form of <b><i>type erasure<\/i><\/b> preserves abstraction across API boundaries, such as different modules. When you expose your publishers as the AnyPublisher type, you can change the underlying implementation over time without affecting existing clients.<\/li>\n<li>As we handled the error using <b>replaceError<\/b> on step 3, this closure will get invoked with an Array of Posts data or an empty array in case of error.<\/li>\n<li>It shows how we can cancel a subscription. (Comment it if testing the code)<\/li>\n<\/ol>\n<p>This is much better. But what about if we don\u2019t want to replace the error with empty data. Let\u2019s fix that.<\/p>\n<p><b>Raising Error and Stricter Network request processing stream:<\/b><\/p>\n<p>Here we are going to update the above-created combine network pipeline to raise errors and normalize them to errors that our Application will understand.<\/p>\n<p>Combine has a family of try-prefixed operators, which accept an error-throwing closure and return a new <i>publisher<\/i>. The publisher terminates with a failure in case an error is thrown inside a closure. Here are some of such methods: tryMap(_:), tryFilter(_:), tryScan(_:_:)<\/p>\n<p>&nbsp;<\/p>\n<div id=\"attachment_55100\" style=\"width: 1778px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/gist.github.com\/ankittlp\/05c32834c742928726ad9b3d493b52a3\"><img aria-describedby=\"caption-attachment-55100\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-55100\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.36.51-AM.png\" alt=\"\" width=\"1768\" height=\"746\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.36.51-AM.png 1768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.36.51-AM-300x127.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.36.51-AM-1024x432.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.36.51-AM-768x324.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.36.51-AM-1536x648.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.36.51-AM-624x263.png 624w\" sizes=\"(max-width: 1768px) 100vw, 1768px\" \/><\/a><p id=\"caption-attachment-55100\" class=\"wp-caption-text\">Custom Error to be used for Networking Layer<\/p><\/div>\n<div id=\"attachment_55101\" style=\"width: 1754px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/gist.github.com\/ankittlp\/05c32834c742928726ad9b3d493b52a3\"><img aria-describedby=\"caption-attachment-55101\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-55101\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.17.48-AM.png\" alt=\"\" width=\"1744\" height=\"1166\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.17.48-AM.png 1744w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.17.48-AM-300x201.png 300w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.17.48-AM-1024x685.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.17.48-AM-768x513.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.17.48-AM-1536x1027.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-07-01-at-1.17.48-AM-624x417.png 624w\" sizes=\"(max-width: 1744px) 100vw, 1744px\" \/><\/a><p id=\"caption-attachment-55101\" class=\"wp-caption-text\"><a href=\"https:\/\/gist.github.com\/ankittlp\/05c32834c742928726ad9b3d493b52a3\"><span style=\"font-weight: 400;\">Network Subscription Stream with Error Handling<\/span><\/a><\/p><\/div>\n<p>Use of <b>tryMap<\/b> over map and use of <b>mapError<\/b> blocks are the main update to our network request processing pipeline.<\/p>\n<ol>\n<li>With the tryMap operator, the response from <b>dataTaskPublisher<\/b> is immediately inspected and we throw an error of desire if the response code is not in range.<\/li>\n<li>Same as the above pattern we decode the response, but there is a commented part, we may use the tryMap closure with normal Decoding and throwing error of our choice if any.<\/li>\n<li>With <b>mapError<\/b> we convert any raised error types down into a common Failure type of <b>APIError<\/b> or <b>ParseError<\/b><\/li>\n<\/ol>\n<p>With the above changes to our pipeline, we achieved the expected error handling.<\/p>\n<p>Wooo!<\/p>\n<p>That was a lot on Combine\u2019s network data processing pipeline.<\/p>\n<p>With all that knowledge we gain in the last part it&#8217;s time to move back on our Network layer Refactoring and apply these.<\/p>\n<p>We\u2019ll go back to our <b>WebApiClient<\/b> class and implement the refactored <b>RequestExecutor <\/b>protocol.<\/p>\n<p>As I have already explained the basic single-shot pipeline using <b>DataTaskPublisher, tryMap, mapError. <\/b>Our refactored WebApiClient will end up as below.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-55171 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.55.11-AM-2.png\" alt=\"\" width=\"1316\" height=\"3028\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.55.11-AM-2.png 1316w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.55.11-AM-2-130x300.png 130w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.55.11-AM-2-445x1024.png 445w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.55.11-AM-2-768x1767.png 768w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.55.11-AM-2-668x1536.png 668w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.55.11-AM-2-890x2048.png 890w, \/blog\/wp-ttn-blog\/uploads\/2022\/07\/Screenshot-2022-06-26-at-12.55.11-AM-2-624x1436.png 624w\" sizes=\"(max-width: 1316px) 100vw, 1316px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/gist.github.com\/ankittlp\/bf42cfc9b11cb3770f895b126e3f30ed\">Link to Combine&#8217;s RequestExecutor Implementation<\/a><\/p>\n<p>The above code is just a combination of all that we learned in Error handling and using Error Mapping. But before I go on to explain the whole Network layer Pipeline, let me remind you of my promise to explain the use of <b>AnyPublisher<\/b> type over <b>DataTaskPublisher<\/b> while refactoring <b>RequestExecutor<\/b> protocol, Here it is !!<\/p>\n<ol>\n<li>Used a <b>Fail<\/b> publisher that immediately terminates with the specified error. And I erase it to any publisher. This is used in case try? request.asURLRequest() fails to create the request and ends up throwing an error. By using AnyPublisher we are able to return any type of publisher even before we create our DataTaskPublisher\u2019s instance.<\/li>\n<li>Just shows that we may also use the CurrentValueSubject publisher to emit an error.<\/li>\n<li>After we have the right request instance we need to create a publisher that actually makes the request call. We do so by creating the DataTaskPublisher instance.<\/li>\n<li>We may have used a map operator, but the mapping operation can throw an error, so we use tryMap instead. Making use of the <b>tryMap<\/b> operator allows us to check the response code and if anything goes wrong we throw an error.<\/li>\n<li>Here again,\u00a0<b>tryMap<\/b> is used for using our old parsers that may also end up throwing errors. Provides us with the flexibility to use our custom parser instead of using the <b>Decode<\/b> operator we saw earlier.<\/li>\n<li>There may be many types of error we may encounter, So to make them one type that our calling code can easily handle we use <b>mapError<\/b> as explained above.<\/li>\n<li>A scheduler that allows us to switch back to the main queue.<\/li>\n<li>Finally, we erase the publisher to any type.<\/li>\n<\/ol>\n<p>This brings us to the end of the article but feel free to check out the demo <a href=\"https:\/\/github.com\/ankittlp\/NetworkingWithCombine\">project<\/a> to learn more about how we end up using this network layer.<\/p>\n<p>Don\u2019t forget to add your api key in WebApiConstants class. Get one from <a href=\"https:\/\/home.openweathermap.org\/api_keys\">here<\/a>.<\/p>\n<p>Also check the use of <b>Generics<\/b>, <b>Protocols<\/b> and <b>Dependency Injection<\/b>.<\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>What is Combine? The Combine Framework &#8211; A framework rolled back in 2019 that works on the fundament of Functional Reactive Programming (FRP) paradigm similar to RxSwift and ReactiveSwift. It is developed by Apple and can be seen as a 1st party alternative to RxSwift and ReactiveSwift. Let\u2019s read from the documentation: Customize handling of [&hellip;]<\/p>\n","protected":false},"author":1138,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":51},"categories":[1400],"tags":[4987,4988,4989],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/55106"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1138"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=55106"}],"version-history":[{"count":8,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/55106\/revisions"}],"predecessor-version":[{"id":55174,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/55106\/revisions\/55174"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=55106"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=55106"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=55106"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}