PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/guides/hack/22-async/02-awaitables.md

https://gitlab.com/Blueprint-Marketing/user-documentation
Markdown | 49 lines | 27 code | 22 blank | 0 comment | 0 complexity | 0b2a180c97796bf0f120b1930be3f28c MD5 | raw file
  1. An *awaitable* is the key construct in `async` code. An awaitable is a first-class Hack object that represents a possibly asynchronous operation that may or may not have completed. You `await` the awaitable until the operation has completed.
  2. ## `Awaitable`
  3. Awaitables are represented through the Hack interface called `Awaitable`. While there are several classes that implement `Awaitable`, there is no need to concern yourself with their implementation details. `Awaitable` is the only interface you need.
  4. The type returned from an async function is `Awaitable<T>`, where `T` is the final result type (e.g., `int`) of the awaited value.
  5. ```
  6. async function foo(): Awaitable<int> {...}
  7. $x = foo(); // $x will be an Awaitable<int>
  8. $x = await foo(); // $x will be an int
  9. ```
  10. @@ awaitables-examples/awaitable-return.php @@
  11. All `async` functions must return an `Awaitable<T>`. Calling an `async` function will therefore yield an object implementing the `Awaitable` interface, and you must `await` or `join` it to obtain an end result from the operation. When you `await`, you are pausing the current task until the operation associated with the `Awaitable` handle is complete, leaving other tasks free to continue executing. `join` is similar, however it blocks all other operations from completing until the `Awaitable` has returned.
  12. ## Awaiting
  13. In most cases, you will prefer to `await` an `Awaitable` so that other tasks can execute while your blocking operation completes. Note however, that only `async` functions can yield control to other asyncs, so `await` may therefore only be used in an `async` function. For other locations, such as a `main` block, you will need to use `join`, outlined later in this section.
  14. ### Batching Awaitables
  15. Many times you will `await` on one `Awaitable`, get the result and move on.
  16. @@ awaitables-examples/single-awaitable.php @@
  17. You will normally see something like `await f();` which combines the retrieving of the awaitable with the waiting and retrieving of the result of that awaitable. The example above separates it out for illustration purposes.
  18. Other times, you will gather up a bunch of awaitables and `await` them all before moving on.
  19. Here we are using one of the two built-in async helper functions in the `HH\Asio` namespace in order to batch a bunch of awaitables together to then `await` upon:
  20. * `HH\Asio\v()`: Indexed list of awaitables with consecutive integer keys
  21. * `HH\Asio\m()`: Associative map of awaitables with integer or string keys
  22. @@ awaitables-examples/multiple-awaitables.php @@
  23. ## Join
  24. Sometimes you want to get a result out of an awaitable when the function you are in **is not** `async`. For this there is `HH\Asio\join()` which takes an `Awaitable` and blocks until it resolves into a result.
  25. This means that invocations of async functions from the global scope (aka psuedomain) cannot be awaited, and must be joined.
  26. @@ awaitables-examples/join.php @@
  27. You should not call `join()` inside an `async` function. This would defeat the purpose of `async` as the awaitable and any dependencies will run to completion synchronously, stopping any other awaitables in their tracks from running. Just `await` in an `async` function.