Error Handling - Async Call

I am creating a framework for the web services used in my project. I uploaded the template to GitHub. https://github.com/vivinjeganathan/ErrorHandling

It has various layers. Level 1 to check. Level 2 to form the request. Level 3 for the actual network call.

View Controller <----> Level 1 <---> Level 2 <---> Level 3

The flow of data between layers through closures, if an error occurs at any level, it should be elegantly passed to the ViewController.

I referred to this link for handling errors on asynchronous calls - http://appventure.me/2015/06/19/swift-try-catch-asynchronous-closures/  Created a branch in the same repo name - ErrorHandling-Method1.

I managed to pass the error from level 3 to level 2 (Single Level - Returning response through functions in closures - as mentioned in the link). But they face difficulties in transferring back through several layers.

Can anyone help with the sample app provided on the publicly available GitHub?

+4
source share
4 answers

First of all, I do not consider it necessary to stack the layers the way you did, for example, adding verification functionality as a layer with which you increase the connection, which makes this layer dependent on the underlying layers (parsing, networking, etc.) , why don't you separate the validation to make it data-dependent only ?:

class ViewController: UIViewController {

   var validator = InputValidator()

   override func viewDidLoad() {
      super.viewDidLoad()

      do {
         try validator.validateInput("INPUT")
         try Fetcher.requestDataWithParams("INPUT")
      }
      catch {
         handleError(error)
      }        
   }
}

, :

View Controller < --- > ParsingLayer < --- > NetworkingLayer

, , .

, , , , :

class NetworkingLayer {
   class func requestData(params: AnyObject, completion: (getResult: () throw -> AnyObject) -> Void) -> Void {
      session.dataTaskWithURL(url) { (data, urlResponse, var error) in
         if let error = error {
            completion(getResult: { throw error })
         } else {
            completion(getResult: { return data })
         }
      }
   }
}

, , , ( ..) ; :

class ParsingLayer {
   class func requestObject(params: AnyObject, completion: (getObject: () throw -> CustomObject) -> Void) -> Void {
      NetworkingLayer.requestData(params, completion: { (getResult) -> Void in
         do {
            let data = try getResult()
            let object = try self.parseData(data)
            completion(getObject: { return object })
         }
         catch {
            completion(getObject: { throw error })
         }
      })
   } 
} 

, , , , , do : , , ; .

, ViewController , , Parsing , , :

override func viewDidLoad() {
   super.viewDidLoad()
   do {
      try validator.validateInput("INPUT")
      try ParsingLayer.requestObject("INPUT", completion: { (getObject) in
      do {
         let object = try getObject()
         try self.validator.validateOutput(object)
         print(object)
      }
      catch {
         self.handleError(error)
      }
   })
   catch {
      handleError(error)
   }        
}

, do catch, , , , , .

, .

+3

, NSError .

:

NSNotificationCenter.defaultCenter().postNotificationName("ErrorEncounteredNotification", object: error)

NSNotificationCenter.defaultCenter().addObserver(self, selector: "errorEncountered:", name: "ErrorEncounteredNotification", object: nil)

:

func errorEncountered(notification: NSNotification!) {
    let error: NSError! = notification.object as! NSError
    NSLog("error: \(error)")
}
+3

, ? throwable .

UPDATE: , . NSNotification - , RXSwift . - RxSwift. , .

+2

.

, : Swift throws. :

func computeSome() throws -> Some

:

func computeSomeAsync(completion: (Some?, NSError?) -> ())

Void . , .

, .

Future:

func computeSomeAsync() -> Future<Some>

- . , ?

, . , . , , , .

, . , .

Depending on the actual implementation and the API of the future library, you can get the result by registering the continuations:

let future = computeSomeAsync()

future.onSuccess { value in
    print("Value: \(value)")
}


future.onFailure { error in
    print("Error: \(error)")
}

It may seem strange at first, but you can do awesome things with futures:

fetchUser(id).flatMap { user in
    fetchProfileImage(user.profileImageUrl).flatMap { image in
        cacheImage(image)
    }
}
.onFailure { error in
    print("Something went wrong: \(error)")
}

The above statement is asynchronous as well as function fetchUser, fetchProfileImageand cacheImage. Error handling enabled.

+2
source

Source: https://habr.com/ru/post/1621506/


All Articles