You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
*[Use Messengers as Promises](#use-messengers-as-promises)
31
+
*[Promises](#promises)
32
+
*[Receive a Promised Value](#receive-a-promised-value)
33
+
*[Compose Promises](#compose-promises)
32
34
*[Variables](#variables)
33
35
*[Observe Variables](#observe-variables)
34
36
*[Use Variable Values](#use-variable-values)
@@ -149,7 +151,7 @@ class Sky: Observable {
149
151
150
152
1. Create a [`Messenger<Message>`](#messengers). It's a mediator through which other entities communicate.
151
153
2. Create an object of a [custom `Observable`](#understand-observables) class that utilizes `Messenger<Message>`.
152
-
3. Create a [`Promise<Value>`](#use-messengers-as-promises). It's a Messenger with conveniences for asynchronous returns.
154
+
3. Create a [`Promise<Value>`](#promises). It's a Messenger with conveniences for asynchronous returns.
153
155
4. Create a [`Variable<Value>`](#variables) (a.k.a. `Var<Value>`). It holds a value and sends value updates.
154
156
5. Create a [*transform*](#make-transforms-observable) object. It wraps and transforms another `Observable`.
155
157
@@ -245,13 +247,15 @@ class Model: SuperModel, Observable {
245
247
}
246
248
~~~
247
249
248
-
## Use Messengers as Promises
250
+
# Promises
249
251
250
-
A `Promise<Value>` is basically just a `Messenger<Value>`. It makes our intention more explicit when we use messengers for managing and chaining asynchronous returns.
252
+
A `Promise<Value>` is basically just a `Messenger<Value>`. It helps managing asynchronous returns and makes that intention more explicit.
251
253
252
254
> **Side Note:**`Promise` is part of SwiftObserver because [Combine's `Future`](https://developer.apple.com/documentation/combine/future) is unfortunately not a practical solution for one-shot asynchronous calls, to depend on [PromiseKit](https://github.com/mxcl/PromiseKit) might be unnecessary in reasonably simple contexts, and [Vapor/NIO's Async](https://docs.vapor.codes/4.0/async/) might also be too server-specific. Anyway, integrating promises as regular observables yields some consistency, simplicity and synergy here. However, at some point *all* promise/future implementations will be obsolete due to [Swift's async/await](https://github.com/DougGregor/swift-evolution/blob/async-await/proposals/nnnn-async-await.md).
253
255
254
-
### Receive a Promised Value
256
+
## Receive a Promised Value
257
+
258
+
### Receive It Once
255
259
256
260
```swift
257
261
funcgetID() -> Promise<Int> { // getID() promises an Int
@@ -267,9 +271,9 @@ getID().observed { id in // observation by FreeObserver.shared
267
271
}
268
272
```
269
273
270
-
Typically, promises are shortlived observables that you don't store anywhere. That works fine since an asynchronous function like `getID()` that returns a promise keeps that promise alive in order to fulfill it. So you can (globally) observe such a promise without even storing it, and the promise as well as its observations get cleaned up automatically when the promise is fulfilled and dies.
274
+
Typically, promises are shortlived observables that you don't hold on to. That works fine since an asynchronous function like `getID()` that returns a promise keeps that promise alive in order to fulfill it. So you can (globally) observe such a promise without even holding it anywhere, and the promise as well as its observations get cleaned up automatically when the promise is fulfilled and dies.
271
275
272
-
### Receive a Promised Value Again
276
+
### Receive It Again
273
277
274
278
Sometimes, you want to do multiple things with an asynchronous result (long) after receiving it. In that case you may keep an [`ObservableCache`](#cached-messages) of the promise, so the promised value will be cached:
275
279
@@ -285,14 +289,14 @@ idCache.whenCached { id in
285
289
}
286
290
```
287
291
288
-
###Compose Promises
292
+
## Compose Promises
289
293
290
294
Inspired by PromiseKit, SwiftObserver allows to compose asynchronous calls using promises.
291
295
292
-
####Sequential Composition
296
+
### Sequential Composition
293
297
294
298
```swift
295
-
promise { //just for nice consistent closure syntax
299
+
promise { //establish context and increase readability
296
300
getInt() // return Promise<Int>
297
301
}.then { // chain another promise sequentially
298
302
getString(takeInt: $0) // take Int sent by 'promise', return Promise<String>
@@ -301,11 +305,11 @@ promise { // just for nice consistent closure syntax
301
305
}
302
306
```
303
307
304
-
`promise` is only for readability. It takes a closure that returns a `Promise` and simply returns that `Promise`.
308
+
`promise` is for readability. It allows for nice consistent closure syntax and makes it clear that we're working with promises. It takes a closure that returns a `Promise` and simply returns that `Promise`.
305
309
306
310
You call `then` on a first `Promise` and pass it a closure that returns the second `Promise`. That closure takes the value of the first promise, allowing the second promise to depend on it. `then` returns a new `Promise` that provides the value of the second promise.
307
311
308
-
####Concurrent Composition
312
+
### Concurrent Composition
309
313
310
314
```swift
311
315
promise {
@@ -320,6 +324,20 @@ promise {
320
324
321
325
You call `and` on a `Promise` and pass it a closure that returns another `Promise`. This immediatly observes both promises. `and` returns a new `Promise` that provides the combined values of both promises.
322
326
327
+
### Value Mapping
328
+
329
+
A transform function that neither filters messages nor exclusively creates a standalone transform will create a new `Promise` when called on a `Promise`. These functions are `map(...)`, `unwrap(default)` and `new()`. The advantage here is, as with any function that returns a promise, that you don't need to keep that observable alive in order to observe it:
330
+
331
+
```swift
332
+
promise {
333
+
getInt()
334
+
}.map { // chain a mapping promise sequentially
335
+
"\($0)"// map Int to String
336
+
}.observed {
337
+
print($0) // print String sent by 'map'
338
+
}
339
+
```
340
+
323
341
# Variables
324
342
325
343
`Var<Value>` is an `Observable` that has a property `value: Value`.
0 commit comments