Skip to content

Commit

Permalink
Merge pull request #15 from async-interop/rename
Browse files Browse the repository at this point in the history
Rename to Promise
  • Loading branch information
trowski authored Nov 14, 2016
2 parents b469819 + 4e0316c commit 4013918
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 29 deletions.
16 changes: 7 additions & 9 deletions META.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Awaitable
# Promise

This document describes a few design considerations, for the main specification, refer to [the README document](README.md).

## Recommended usage of Awaitable
## Recommended usage of Promises

We are explicitly _not_ providing a chainable method, thus we are also not recommending to chain them, but rather to use coroutines in form of generators inside application code.

Expand All @@ -12,16 +12,14 @@ Coroutines solve the problem of the so-called callback hell very nicely and also

The specification proposes `when()` in order to only expose the most primitive common denominatior needed for interoperability, which is a simple callable to be executed after the resolution.

If implementations wish to adhere to e.g. [Promises/A+ from Javascript](https://promisesaplus.com) (which had been implemented in many PHP Promise libraries at the time of writing this specification) or implement any other methods, they still may do so; `when()` however is the fundamental interoperable primitive every `Awaitable` is guaranteed to have.
If implementations wish to adhere to e.g. [Promises/A+ from Javascript](https://promisesaplus.com) (which had been implemented in many PHP Promise libraries at the time of writing this specification) or implement any other methods, they still may do so; `when()` however is the fundamental interoperable primitive every `Promise` is guaranteed to have.

Additionally, coroutines do not use the returned `Promise` of a `then` callback, but returning a `Promise` is required by Promises/A+. Thus there's a lot of useless object creations when using Awaitables the recommended way, which isn't cheap and adds up. This conflicts with the goal of being as lightweight as possible.
Additionally, coroutines do not use the returned `Promise` of a `then` callback, but returning a `Promise` is required by Promises/A+. Thus there's a lot of useless object creations when using Promises the recommended way, which isn't cheap and adds up. This conflicts with the goal of being as lightweight as possible.

## Naming

As we are not using a thenable, which is sometimes associated with the word `Promise`, we decided against using `Promise`.
Even though we are not using a thenable, `Promise` is a more recognizable and accepted name for future value placeholders.

Thus, `Awaitable` was a logical choice, with [HHVM already having it](https://docs.hhvm.com/hack/reference/interface/HH.Awaitable/) and PHP possibly also being some day extended to natively support an `await` keyword.
## Creation of Promises

## Creation of Awaitables

Awaitable creation and managing is out of scope of this specification, as managing never shall cross library boundaries and thus does not need to be interoperable at all; each library shall resolve the Awaitable it created itself.
Promise creation and managing is out of scope of this specification, as managing never shall cross library boundaries and thus does not need to be interoperable at all; each library shall resolve the Promise it created itself.
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
# Awaitable
# Promise

The purpose of this proposal is to provide a common interface for simple placeholder objects returned from async operations. This will allow libraries and components from different vendors to create coroutines regardless of the used placeholder implementation. This proposal is not designed to replace promise implementations that may be chained. Instead, this interface may be extended by promise implementations.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119][].

An `Awaitable` represents the eventual result of an asynchronous operation. Interaction with an `Awaitable` happens through its `when` method, which registers a callback to receive either an `Awaitable`'s eventual value or the reason why the `Awaitable` has failed.
A `Promise` represents the eventual result of an asynchronous operation. Interaction with a `Promise` happens through its `when` method, which registers a callback to receive either a `Promise`'s eventual value or the reason why the `Promise` has failed.

`Awaitable` is the fundamental primitive in asynchronous programming. It should be as lightweight as possible, as any cost adds up significantly.
`Promise` is the fundamental primitive in asynchronous programming. It should be as lightweight as possible, as any cost adds up significantly.

This specification defines the absolute minimums for interoperable coroutines, which can be implemented in PHP using generators.

This specification does not deal with how to create, succeed or fail `Awaitable`s, as only the consumption of `Awaitable`s is required to be interoperable.
This specification does not deal with how to create, succeed or fail `Promise`s, as only the consumption of `Promise`s is required to be interoperable.

For further design explanations and notes, please refer to [the meta document](META.md).

## Terminology

1. _Awaitable_ is an object implementing `Interop\Async\Awaitable` and conforming to this specification.
2. _Value_ is any legal PHP value (including `null`), except an instance of `Interop\Async\Awaitable`.
1. _Promise_ is an object implementing `Interop\Async\Promise` and conforming to this specification.
2. _Value_ is any legal PHP value (including `null`), except an instance of `Interop\Async\Promise`.
3. _Error_ is any value that can be thrown using the `throw` statement.
4. _Reason_ is an error indicating why an `Awaitable` has failed.
4. _Reason_ is an error indicating why a `Promise` has failed.

## States

An `Awaitable` MUST be in one of three states: `pending`, `succeeded`, `failed`.
A `Promise` MUST be in one of three states: `pending`, `succeeded`, `failed`.

| A promise in … state |   |
|----------------------|--------|
Expand All @@ -37,7 +37,7 @@ An `Awaitable` MUST be in one of three states: `pending`, `succeeded`, `failed`.

## Consumption

An `Awaitable` MUST implement `Interop\Async\Awaitable` and thus provide a `when` method to access its current or eventual value or reason.
A `Promise` MUST implement `Interop\Async\Promise` and thus provide a `when` method to access its current or eventual value or reason.

```php
<?php
Expand All @@ -47,10 +47,10 @@ namespace Interop\Async;
/**
* Representation of a the future value of an asynchronous operation.
*/
interface Awaitable
interface Promise
{
/**
* Registers a callback to be invoked when the awaitable is resolved.
* Registers a callback to be invoked when the promise is resolved.
*
* @param callable(\Throwable|\Exception|null $exception, mixed $result) $onResolved
*
Expand All @@ -68,13 +68,13 @@ The `when` method MUST accept at least one argument:
function($error, $value) { /* ... */ }
```

Any implementation MUST at least provide these two parameters. The implementation MAY extend the `Awaitable` interface with additional parameters passed to the callback. Further arguments to `when` MUST have default values, so `when` can always be called with only one argument. `when` MAY NOT return a value. `when` MUST NOT throw exceptions bubbling up from a callback invocation.
Any implementation MUST at least provide these two parameters. The implementation MAY extend the `Promise` interface with additional parameters passed to the callback. Further arguments to `when` MUST have default values, so `when` can always be called with only one argument. `when` MAY NOT return a value. `when` MUST NOT throw exceptions bubbling up from a callback invocation.

> **NOTE:** The signature doesn't specify a type for `$error`. This is due to the new `Throwable` interface introduced in PHP 7. As this specification is PHP 5 compatible, we can use neither `Throwable` nor `Exception`.
All registered callbacks MUST be executed in the order they were registered. If one of the callbacks throws an `Exception` or `Throwable`, it MUST be rethrown in a callable passed to `Loop::defer` so `Loop::onError` can be properly invoked by the loop. `Loop` refers to the [global event loop accessor](https://github.com/async-interop/event-loop/blob/master/src/Loop.php). The `Awaitable` implementation MUST then continue to call the remaining callbacks with the original parameters.
All registered callbacks MUST be executed in the order they were registered. If one of the callbacks throws an `Exception` or `Throwable`, it MUST be rethrown in a callable passed to `Loop::defer` so `Loop::onError` can be properly invoked by the loop. `Loop` refers to the [global event loop accessor](https://github.com/async-interop/event-loop/blob/master/src/Loop.php). The `Promise` implementation MUST then continue to call the remaining callbacks with the original parameters.

If an `Awaitable` is resolved with another `Awaitable`, the `Awaitable` MUST keep in pending state until the passed `Awaitable` is resolved. Thus, the value of an `Awaitable` can never be an `Awaitable`.
If a `Promise` is resolved with another `Promise`, the `Promise` MUST keep in pending state until the passed `Promise` is resolved. Thus, the value of a `Promise` can never be a `Promise`.

## Contributors

Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "async-interop/awaitable",
"description": "An awaitable interface for implementing async operations",
"keywords": ["awaitable", "async", "interop"],
"name": "async-interop/promise",
"description": "Promise interface for implementing async operations",
"keywords": ["promise", "future", "awaitable", "async", "interop"],
"license": "MIT",
"require": {
"php": ">=5.4"
Expand Down
6 changes: 3 additions & 3 deletions src/Awaitable.php → src/Promise.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
namespace Interop\Async;

/**
* Awaitable object representing the future value of an asynchronous operation.
* Promise object representing the future value of an asynchronous operation.
*/
interface Awaitable
interface Promise
{
/**
* Registers a callback to be invoked when the awaitable is resolved.
* Registers a callback to be invoked when the promise is resolved.
*
* @param callable(\Throwable|\Exception|null $exception, mixed $result) $onResolved
*
Expand Down

0 comments on commit 4013918

Please sign in to comment.