Promises are a new primitive in JavaScript that allow you to write asynchronous code without having to deal with callbacks or promises. They have been adopted by the likes of React and Angular, but there’s still a lot of confusion about how they work.
The alamofire is a networking library built on promises for swift. It makes it easy to build web services that are responsive and performant.
Description
Breaking waves, palm palms, and coral reefs Welcome to the Malibu Surf Club, a promise-filled networking library. It’s more than simply a wrapper for URLSession; it’s a sophisticated framework for chaining requests, validations, and processing.
Using Malibu provides a bunch of sweet helpers behind the hood and takes your code to the next level:
- There will be no more “callback hell.”
- All of your requests are listed in one location.
- Response processing may be readily divided into a number of logical steps.
- Errors and data are handled independently.
- Your networking code is much more understandable and adheres to the DRY principle.
Equip yourself with the appropriate Malibu gear, become a large wave surfer, and put an end to the days of shark-infested asynchronous networking. Have fun on the ride!
Features
- Several network stacks
- Requests that are made explicitly
- Promise-based response callbacks that can be chained
- All content types and parameter encodings are required.
- Validation of HTTP responses
- Serialization of response data
- a sarcastic response
- Logging of requests, responses, and errors
- There are two types of modes: synchronous and asynchronous.
- Pre-processing and middleware for requests
- Make a request for offline storage.
- Coverage of unit tests is extensive.
Contents Table of Contents
Taking advantage of the opportunity
You can start riding right immediately without having to worry about configurations:
GET http://sharkywaters.com/api/boards?type=1 http://sharkywaters.com/api/boards?type=1 let request = Request.get(“http: sharkywaters.com api boards”, [“type”: 1]), parameters: Make a request using Malibu.request(request). validate() is a function that checks whether or not something is valid. then(dictionary -> [Board] in / toJsonDictionary().then(dictionary -> [Board] in Let’s assume we’re mapping return try dictionary.relationsOrThrow(“boards”) as [Board] ) using https://github.com/zenangst/Tailor. / Handle response data done(boards in) fail(error in / Error Handling) always( in / Hide progress bar) in in in in in in in in ”> => Make your request GET http://sharkywaters.com/api/boards?type=1 let request = Request.get(“http://sharkywaters.com/api/boards”, [“type”: 1]), parameters: Make a request using Malibu.request(request). validate() is a function that checks whether or not something is valid. then(dictionary -> [Board] in / toJsonDictionary().then(dictionary -> [Board] in Let’s assume we’re mapping return try dictionary.relationsOrThrow(“boards”) as [Board] ) using https://github.com/zenangst/Tailor. / Handle response data done(boards in) fail(error in / Error Handling) always( in / Hide progress bar) in in in in in in in in
If you’re still not seeing any advantages, keep scrolling down and prepare yourself for even more magic…
RequestConvertible
To deal with numerous API services, we usually require distinct network stacks. With Malibu, archiving is a breeze. Create an enum that adheres to the RequestConvertible protocol and list all of the attributes for your requests:
enum RequestConvertible: SharkywatersEndpoint / Describe requests case fetch The case of the boards demonstrates Create a board(id: Int) case Case update for Board(type: Int, title: String) case delete (id: Int, type: Int, title: String) / Board(id: Int) The base url will be used to scope all requests. / The use of a base url is encouraged, but it is not required. baseUrl: URLStringConvertible? = “http://sharkywaters.com/api/” static var baseUrl: URLStringConvertible? = “http://sharkywaters.com/api/” Every request has its own set of headers. [String: String] [String: String] [String: String] [String: String] [String: String] [ [ “Accept” : “application/json” ] = [ “Accept” : “application/json” ] / Create requests var request: Request self-switch .fetch case Return Request.get(“boards”) in the case.show case.createBoard(let type, let title): return Request.post(“boards”, parameters: [“type”: type, “title”: title]) case.updateBoard(let type, let title): return Request.get(“boards/(id)”) case.updateBoard(let type, let title): return Request.get(“boards/(id)”) case.updateBoard(let type, let title): return Request.patch(“boards/(id)”, parameters: [“title”: title]) case.delete Board(let id, let title): return Request.patch(“boards/(id)”, parameters: [“title”: title]) case.delete Return Request.delete(“boards/(id)”) from Board(let id)
The headers Accept-Language, Accept-Encoding, and User-Agent are automatically added.
Request
In Malibu, a request is described as a struct:
let request = Request( / HTTP method method:.get, get, get, get, get, get, get, get, get, get, get, get, / Resource url or path: “boards”, / Content type:.query, / Request parameters parameters: / Headers headers: [“custom”: “header”], / Offline storage configuration store [“type”: 1, “text”: “traditional”], / / Policy on caching cache, policy:.unspecified .useProtocolCachePolicy)))))))))))))))))))))))
For each HTTP method, there are several helper methods with default values:
/ GET GET GET GET GET GET GET GET GET Request.get = Request (“boards”) / GET REQUEST GET REQUEST GET REQUEST GET RE Request = Request.post( “boards”, “request”, “request”, “request”, “request”, ” / For POST contentType:.formURLEncoded, parameters: [“kind” : kind, “title” : title]), the content type is set to.json by default. / Let’s make a PUT request. [“type” : kind, “title” : title]) = Request.put(“boards/1”, parameters: [“type” : kind, “title” : title]) = Request.put(“boards/1”, parameters: [“type” : kind, ” PATCH is a request that allows you to make changes to your code. [“title” : title]) = Request.patch(“boards/1”, parameters: [“title” : title]) = Request.patch(“boards/1”, parameters: [“title” : title]) / Let’s remove the DELETE request. Request.delete(“boards/1”) = Request.delete(“boards/1”) = Request.delete(“boards
The default task for performing requests is URLSessionDataTask. There are two more methods for uploading that utilize URLSessionUploadTask rather than URLSessionDataTask.
/ Add data to the link upload.request (data: data, to: “boards”) / Parameterized multipart data upload / You’re in charge of creating a suitable value, which is usually a string made up of data. multipart.request.upload to: “http:/api.loc/posts” ) parameters: [“key”: “value”]
Types of content
- query – generates a query string that may be added to any url.
- formURLEncoded – utilizes the Content-Type application/x-www-form-urlencoded and percent-encodes your arguments.
- json – sets the Content-Type to application/json and transmits the body of the request as a JSON representation of the arguments.
- multipartFormData — transmits multipart/form-data encoded parameters.
- custom(String) – acts as a header for the supplied Content-Type string.
Encoding
Malibu comes with three different parameter encoding options:
- FormURLEncoder — an RFC 3986-compliant percent-escaped encoding.
- JsonEncoder – Encoding based on JSONSerialization.
- MultipartFormEncoder is a data constructor that divides data into many parts.
By implementing a custom parameter encoder that follows the ParameterEncoding protocol, you may expand the default functionality:
/ Override Malibu.parameter’s default JSON encoder CustomJsonEncoder[.json] = Encoders[.json] () / Register an encoder for the Malibu.parameter custom encoding type. CustomXMLEncoder[.custom(“application/xml”)] = Encoders[.custom(“application/xml”)] = Encoders[.custom(“application/xml”)] = ()
Cache policy
The URLSession uses the URLRequest.CachePolicy attribute to manage cache:
Let’s get started. Request is the same as Request. get(“boards”. useProtocolCachePolicy) cachePolicy:.useProtocolCachePolicy) cachePolicy:.useProtocolCachePolicy)
URLRequest.CachePolicy.useProtocol The default policy for URL load requests is CachePolicy. Before delivering the request to the backend, URLSession will automatically include the If-None-Match header. When the 304 Not Modified response status is received, URLSession will execute the URLSessionDataTask completion block with the 200 status code and data loaded from the cached response.
If you wish to disable automated cache management, set the cachePolicy property to.reloadIgnoringLocalCacheData. The If-None-Match header will not be included to client requests, and the server will always provide a complete answer.
Networking
Malibu’s Networking class is a fundamental component that performs real HTTP queries against a given API service.
Initialization
To start a new Networking instance, follow these steps:
Let simpleNetworking = Networking be the default value ()
/ More sophisticated networking allow networking to equal networking Default, ephemeral, background, or custom session ( / OperationQueue Mode mode:.async, / Optional mock provider mockProvider: customMockProvider, / default, ephemeral, background, or custom session sessionDelegate: self ) “> Configuration:.default, / Custom URLSessionDelegate may be specified if required.
/ Simple networking for SharkywatersEndpoint requests. make it simple Networking equates to networking () / More sophisticated networking allow networking to equal networking (OperationQueue) ( mode.async, mode.async, mode.async, mode.asy Mock provider (optional) customMockProvider, customMockProvider, customMockProvider, customMockProvider, customMock / session types: default, ephemeral, background, or custom Default settings are:.default,.default,.default,.default,.default,. If required, a custom URLSessionDelegate may be specified (sessionDelegate: self ).
Malibu executes/cancels requests via OperationQueue. It makes request lifetime and concurrency management much simpler.
There is an optional parameter when creating a new networking instance to indicate the mode that will be used:
When it comes to creating tests, mocking is very useful. However, it has the potential to speed up your development while the backend engineers are focused on API implementation.
“>