nevyn — promise, it's async! swift language user group lightning talk 2015-09-24

28
Promise, it's async! SLUG Lightning 2015-09-24 @nevyn, @lookback

Upload: joachim-bengtsson

Post on 13-Jan-2017

287 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Promise, it's async!SLUG Lightning 2015-09-24@nevyn, @lookback

Page 2: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

SPAsync

Page 3: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Nested scopes!.fetchFromNetwork(input) { intermediate in !.parseResponse(intermediate) { again in dispatch_async(dispatch_get_main_queue()) { updateUI(output) } }}

Page 4: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Error handling

!.fetchFromNetwork(input, callback: { intermediate in !.parseResponse(intermediate, callback: { again in dispatch_async(dispatch_get_main_queue()) { updateUI(output) } }, errback: { error in displayError("when parsing response, ", error) })}, errback: { error in // This error is VERY far away from fetchFromNetwork! displayError("when fetching from network, ", error)})

Page 5: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Cancellation

var cancelled = falseblock var cancellable : Cancellable?let operation = !.fetchFromNetwork(input, callback: { intermediate in if(cancelled) return cancellable = !.parseResponse(intermediate, callback: { again in if(cancelled) return ... })})

func cancel() { cancelled = true operation.cancel() cancellable?.stopOperation()}

Page 6: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Dependencies

func !()...

Page 7: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Four async concepts» A-value-in-the-future

» Error handler

» Cancellation

» Dependencies

Page 8: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

GCD?NSOperation?

Page 9: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

ReactiveCocoa?

Page 10: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

C♯

Page 11: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Task/ "promise" / "future"

Page 12: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Help me Apple, you're my only hope!» A-value-in-the-future

» Error handler

» Cancellation

» Dependencies

... IN FOUNDATION

Page 13: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

SPTask.swift 1/4class TaskCompletionSource<T> { public let task: Task<T> func completeWithValue(value: T) func failWithError(error: NSError!)}

Page 14: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

SPTask.swift 2/4class Task<T> { public func addCallback( on queue: dispatch_queue_t, callback: (T -> Void) ) -> Self

public func addErrorCallback( on queue: dispatch_queue_t, callback: (NSError! -> Void) ) -> Self

public func addFinallyCallback( on queue: dispatch_queue_t, callback: (Bool -> Void) ) -> Self}

Page 15: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Callback example

// Two of these three are executed immediately after each othernetwork.fetch(resource).addCallback { json in let modelObject = parse(json) updateUI(modelObject)}.addErrback { error in displayDialog(error)}.addFinally { cancelled in if !cancelled { viewController.dismiss() }}

Page 16: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

SPTask.swift 3/4class Task<T> { public func then<T2>(on queue:dispatch_queue_t, worker: (T -> T2)) -> Task<T2> public func then<T2>(chainer: (T -> Task<T2>)) -> Task<T2>}

Page 17: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Chaining example

// A: inline background parsing on _worker_queuefunc parse<T>(json) -> T

network.fetch(resource) .then(on: _worker_queue) { json in // First this function runs, running parse on _worker_queue... return parse<MyModel>(json) }.addCallback { modelObject in // ... and when it's done, this function runs on main updateUI(modelObject) }.addErrorCallback { ... }

// B: background parsing on Parser's own thread with async methodclass Parser { func parse<T>(json) -> Task<T>}

network.fetch(resource) .then(_parser.parse) // parser is responsible for doing async work on its own .addCallback(updateUI) // and then updateUI is called with the model object .addErrorCallback(displayError)

Page 18: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

SPTask.swift 4/4class Task<T> { public func cancel()

static func awaitAll(tasks: [Task]) -> Task<[Any]>}

Page 19: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

cancel and awaitAll example

let imagesTask = Task.awaitAll(network.fetchImages(resource)).then { imageDatas in return Task.awaitAll(imageDatas.map { data in return parseImage(data) })}.addCallback { images in showImages(image)}

func viewDidDisappear(){

// All downloading and parsing is cancelled imagesTask.cancel()}

Page 20: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Grand finale

Page 21: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Task.wrap()

Page 22: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

class NSURLConnection { func sendAsynchronousRequest( request: NSURLRequest, queue: NSOperationQueue, completionHandler: (NSURLResponse?, NSError?) -> Void )}

extension NSURLConnection { // : (NSURLRequest, queue) -> Task<NSURLResponse?> let asyncTaskRequest = Task.wrap(NSURLConnection.sendAsynchronousRequest)}

NSURLConnection.asyncTaskRequest(myRequest, mainQueue) .then(_parser.parse) .then(_db.store) .then(_ui.update)

Page 23: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

extension Task { func wrap<P1, P2, R1> ( asyncFunction: ( p1: P1, p2: P2, callback: ( r1: R1, err: NSError? ) -> Void ) -> Void ) -> (P1, P2) -> Task<R1>}

Page 24: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

extension Task { func wrap<P1, P2, R1> ( asyncFunction: ( p1: P1, p2: P2, callback: ( r1: R1, err: NSError? ) -> Void ) -> Void ) -> (P1, P2) -> Task<R1> { let source = TaskCompletionSource<R1>()

return { (p1: P1, p2: P2) -> Task<R1> in asyncFunc(p1: p1, p2: p2, callback: { (r1: R1, error: NSError?) -> Void in if let error = error { source.failWithError(error) } else { source.completeWithValue(r1) } }) return source.task } }}

Page 25: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Functional Task?Monads? Applicatives? Huh?!

Page 26: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Blog: Methods of Concurrency 

http://bit.do/concurrencyhttp://overooped.com/post/41803252527/methods-of-concurrency

Page 27: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24
Page 28: Nevyn — Promise, It's Async! Swift Language User Group Lightning Talk 2015-09-24

Thank you@[email protected]