Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Promise, Promise

Promise, Promise

Using promises in android and iOS development

Vlad Vysotsky

December 08, 2016
Tweet

More Decks by Vlad Vysotsky

Other Decks in Programming

Transcript

  1. Працюю Android, iOS developer Балуюсь Groovy on grails, Angular Kotlin&Swift

    lover email: [email protected] gh: www.github.com/vysotsky fb: https://www.facebook.com/wolltone Мене звати Влад
  2. Hey mama, look at me I'm on my way to

    the promised land, whoo! I'm on the highway to callback hell -Brian Johnson, AC/DC
  3. Що таке Promise? Основна ідея полягає в тому, що Promise

    - результат асинхронної операції. Він може бути в одному з трьох різних станів: • pending - початковий стан; • fulfilled - стан, що представляє успішну операцію; • rejected - стан, що представляє невдалу операцію. Після виконання Promise залишиться незмінним.
  4. Rx або Promise Promise - “async single value” - task

    parallelization model Rx - “async list of values” - reactive extension model
  5. required public init(resolvers: (_ fulfill: @escaping (T) -> Void, _

    reject: @escaping (Error) -> Void) throws -> Void)
  6. let foo = Promise<UIImage> { fulfill, reject in guard let

    image = try downloadImage() else { return reject(ImageError.noImage) } fulfill(image) }
  7. firstly { UIApplication.shared.isNetworkActivityIndicatorVisible = true return when(fulfilled: URLSession.dataTask(with: url).asImage(), CLLocationManager.promise())

    }.then { image, location in self.imageView.image = image self.label.text = "\(location)" }.always { UIApplication.shared.isNetworkActivityIndicatorVisible = false }.catch { error in UIAlertView(with: error.localizedDescription).show() }
  8. func fetchInBackground(logins: [String]) -> Promise<UIBackgroundFetchResult> { return race(after(interval: 20).then {

    throw CustomError.error }, when(fulfilled: logins.map(downloadUser)) .then { users -> UIImage? in return try self.makeSomething(with: users) }.then { _ -> Void in AppDelegate.coreDataProvider.saveContext() }.then { return Promise(value: .newData) }.recover { error in Analytics.log(error) return Promise(value: .failed) }) }
  9. func login() -> Promise<User> { UIApplication.shared.isNetworkActivityIndicatorVisible = true return firstly

    { Alamofire.request(url, method: .get).responseData() }.then(on: DispatchQueue.global()) { data in convertToUser(data) }.always { UIApplication.shared.isNetworkActivityIndicatorVisible = false } }
  10. final TaskCompletionSource<GenericObject> tcs = new TaskCompletionSource<>(); tcs.setResult(object); //it should be

    called inside the async block tcs.setError(e); //in case of error return tcs.getTask();
  11. saveAsync(obj).continueWith(new Continuation<ParseObject, Void>() { public Void then(Task<ParseObject> task) throws Exception

    { if (task.isCancelled()) { // the save was cancelled. } else if (task.isFaulted()) { // the save failed. Exception error = task.getError(); } else { ParseObject object = task.getResult(); } return null; } });
  12. loadUsersAsync(query).onSuccessTask(new Continuation<List<User>, Task<Something>>() { public Task<Something> then(Task<List<Users>> task) throws Exception

    { return makeSomethingAsync(task.getResult()); } }).onSuccessTask(new Continuation<Something, Task<SometingElse>>() { public Task<SometingElse> then(Task<Something> task) throws Exception { return makeSomethingElseAsync(task.getResult()); } }).onSuccess(new Continuation<SometingElse, Void>() { public Void then(Task<SometingElse> task) throws Exception { return null; } });
  13. loadUsersAsync(query).onSuccessTask(new Continuation<List<User>, Task<Something>>() { public Task<Something> then(Task<List<Users>> task) throws Exception

    { throw new RuntimeException("There was an error."); return makeSomethingAsync(task.getResult()); } }).onSuccessTask(new Continuation<Something, Task<SometingElse>>() { public Task<SometingElse> then(Task<Something> task) throws Exception { //skipped return makeSomethingElseAsync(task.getResult()); } }).continueWith(new Continuation<SometingElse, Void>() { public Void then(Task<SometingElse> task) throws Exception { //will be called return null; } });
  14. Task.call(new Callable<HttpResponse>() { @Override public HttpResponse call() throws Exception {

    return client.execute(request); } }, NETWORK_EXECUTOR).continueWithTask(new Continuation<HttpResponse, Task<byte[]>>() { @Override public Task<byte[]> then(Task<HttpResponse> task) throws Exception { return processResponseAsync(response); } }).continueWithTask(new Continuation<byte[], Task<Void>>() { @Overrid public Task<Void> then(Task<byte[]> task) throws Exception { return writeToDiskAsync(task.getResult()); } }, DISK_EXECUTOR);
  15. dependencies { // Facebook Dependencies compile 'com.android.support:support-v4:25.0.0' compile 'com.android.support:appcompat-v7:25.0.0' compile

    'com.android.support:cardview-v7:25.0.0' compile 'com.android.support:customtabs:25.0.0' compile 'com.parse.bolts:bolts-android:1.4.0' … } Вони вже у вашому проекті...
  16. Отже, Promise 1. упорядковують асинхронні задачі 2. спрощують відловлювання помилок

    3. унифікують все до одного стандарту 4. просто круті і круто виглядають
  17. Отже, Promise 1. упорядковують асинхронні задачі 2. спрощують відловлювання помилок

    3. унифікують все до одного стандарту 4. просто круті і круто виглядають
  18. DIY: async/await на iOS let asyncQueue = DispatchQueue(label: "asyncQueue", attributes:

    .concurrent) let awaitQueue = DispatchQueue(label: "awaitQueue", attributes: .concurrent)
  19. DIY: async/await на iOS func async(_ body: @escaping () throws

    -> Void) { promise(execute: body).catch { _ in } }
  20. DIY: async/await на iOS func await<Result>(_ body: @escaping () throws

    -> T) throws -> T { guard label != DispatchQueue.main.label else { throw Error.lockedCurrentThread } var result: Result? var error: Error? let semaphore = DispatchSemaphore(value: 0) promise(execute: body).then(on: self) { val -> Void in result = val semaphore.signal() }.catch(on: self) { err in error = err semaphore.signal() } _ = semaphore.wait(timeout: DispatchTime(uptimeNanoseconds: UINT64_MAX)) guard let result = result else { throw Error.badResult } return result }
  21. DIY: async/await на iOS func setupNewUser(name: String) -> Promise<User> {

    return async { let newUser = try await(self.createUser(name)) //createUser returns Promise let friends = try await(self.getFacebookFriends(name)) newUser.addFriends(friends) return newUser } }
  22. fun loadStringAsync() = async<String> { val secondsToWait = 3 println("Started!")

    println("Waiting $secondsToWait seconds...") for (n in 0 until secondsToWait) { waitAsync(1.seconds).await() println("One second elapsed!") } println("Downloading url...") val result = MyNetTasks.downloadGoogleAsStringAsync().await() println("Downloaded") result } Kotlin async/await
  23. public class Store { public CompletableFuture<Boolean> buyItem(String itemTypeId, int cost)

    { if(!await(bank.decrement(cost))) { return completedFuture(false); } try { await(inventory.giveItem(itemTypeId)); return completedFuture(true); } catch (Exception ex) { await(bank.refund(cost)); throw new AppException(ex); } } } EA async/await для Java
  24. Android lifecycle + Promise 1. Не писати код в activity/fragment

    2. Але можна писати в retained instance 3. Можна юзати в сервісах, лоадерах 4. Якщо є архітектура (MVC, MVP, MVVM, MV*), то можна щось придумати
  25. QA