Skip to content

Document Promise #68

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 64 additions & 6 deletions components/promise.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,71 @@
Promise
=======

Promise used for asynchronous HTTP requests.

This will eventually be removed/deprecated and replaced with the upcoming Promise PSR.
When sending asynchronous HTTP requests, a promise is returned. The promise acts
as a proxy for the response or error result, which is not yet known.
The PHP-HTTP promise follows the `Promises/A+`_ standard.

.. note::

Contract for the ``Http\Promise\Promise`` is temporary until `PSR is released`_.
Once it is out, we will use this PSR in the main client and deprecate the old contract.
Work is underway for a `Promise PSR`_. When that PSR has been released, we
will use it in HTTPlug and deprecate our ``Http\Promise\Promise`` interface.

Asynchronous requests
---------------------

Asynchronous requests enable non-blocking HTTP operations. To execute such a
request with HTTPlug::

$request = $messageFactory->createRequest('GET', 'http://php-http.org');

// Where $client implements HttpAsyncClient
$promise = $client->sendAsyncRequest($request);

// This code will be executed right after the request is sent, but before
// the response is returned.
echo 'Wow, non-blocking!';

See :ref:`message-factory` on how to use message factories.

Wait
----

The ``$promise`` that is returned implements ``Http\Promise\Promise``. At this
point in time, the response is not known yet. You can be polite and wait for
that response to arrive::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should mention that you could do several async requests in parallel and then wait for each (allowing the other requests to resolve while we wait)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this happening in the batch client?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, as that is usually the idea of doing asynchronous requests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s document this in a separate Batch client chapter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay. we can add a note in this chapter when we add the batch client chapter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #73.


try {
$response = $promise->wait();
} catch (\Exception $exception) {
echo $exception->getMessage();
}

Then
----

Instead of waiting, however, you can handle things asynchronously. Call the
``then`` method with two arguments: one callback that will be executed if the
request turns out to be successful and/or a second callback that will be
executed if the request results in an error::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we link to something that explains reactphp and similar async friendly systems? and the loop.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a suggestion?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joelwurtz is our async expert, maybe he has an idea?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be very welcome!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could even link to the Promise A+ spec?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how dry is that spec? is it a good first read, or a hard to grok reference? maybe if joel could write a nice introduction and then reference the spec and other further reading, we could link to that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You decide: https://promisesaplus.com/

At least mentioning the fact that we are implementing that spec (and placing a link to it)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, we definitely should say that our Promise interface is inspired by promiseaplus.com . but i think a blogpost explaining async in a PHP context would be a good addition.

and i notice i put that comment in the middle of something - we probably should extend the introduction rather than place that here in the middle of everything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I added a reference to Promises/A+. We can add a link to an introduction (by @joelwurtz or otherwise) separately.


$promise->then(
// The success callback
function (ResponseInterface $response) {
echo 'Yay, we have a shiny new response!';

// Write status code to some log file
file_put_contents('responses.log', $response->getStatusCode() . "\n", FILE_APPEND);

return $response;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the point of returning the response here? that will do nothin i think. maybe we should find a better example what to do.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like updating a file or database with the contents of a json response

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know, really. I copied this from the tutorial. 😉

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea either.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should avoid duplication between doc. keep the tutorial minimal, or use a partial if the same example really makes sense (or just link)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, some redundancy in a tutorial chapter is ok - the references serve a different purpose and a tutorial without code examples and tons of links is not helpful. ideally the tutorial will "tell a story". it could mention working with promise as a side note as a tutorial on promise would be a large topic of its own...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True: the tutorial should be a kind of story that is easy to follow. Too many links will distract too much and disrupt the flow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, duplication is bad from two points of view: content and maintenance. The former is arguable: for the sake of completeness, it might be good. If we can utilize partials to avoid maintenance of duplication, that's at least a half win.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay. but can we turn this into a minimal useful example? like write the response body into a file? returning something makes no sense at all.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ups, already merged, but: @joelwurtz does returning the response make any sense here or should we just file_put_contents for the example? i assume the thing resolving the promise is not handling any return values?

},

// The failure callback
function (\Exception $exception) {
echo 'Oh darn, we have a problem';

throw $exception;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will just explode the application, right @joelwurtz ? but it will not be swallowed, so its reasonable to do this?

}
);

.. _`PSR is released`: https://groups.google.com/forum/?fromgroups#!topic/php-fig/wzQWpLvNSjs
.. _`Promise PSR`: https://groups.google.com/forum/?fromgroups#!topic/php-fig/wzQWpLvNSjs
.. _Promises/A+: https://promisesaplus.com
4 changes: 4 additions & 0 deletions httplug/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ will return of one ``Promise::PENDING``, ``Promise::FULFILLED`` or ``Promise::RE
Then you can get the response of the promise if it's in ``FULFILLED`` state with ``$promise->getResponse()`` call or
get the error of the promise if it's in ``REJECTED`` state with ``$promise->getRequest()`` call

.. note::

Read :doc:`/components/promise` for more information about promises.

Example
^^^^^^^

Expand Down