Skip to content

Instantly share code, notes, and snippets.

@bzikarsky
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bzikarsky/4794f640b60ce6befd49 to your computer and use it in GitHub Desktop.
Save bzikarsky/4794f640b60ce6befd49 to your computer and use it in GitHub Desktop.
Resolvable generators
<?php
// this is our generator, dns\* and socket\* are assumed
// to be async functions returning promises
function read_data_from($hostname, $port) {
$ip = yield dns\resolve($hostname);
$socket = yield socket\connect($ip, $port);
echo yield socket\read(1024);
};
// Let's schedule it
//
// Maybe we can also change the event-loop to automatically
// try to resolve Generators in the tick handlers
$loop->nextTick(function() {
React\Promise\resolve(read_data_from('google.com', 80));
});
<?php
// Changes to React\Promise\resolve
// They probably should be pushed to a separate function
function resolve($promiseOrValue = null)
{
// a generator is resolved when the iterator is invalid
// then it can be used like a normal value (FullfilledPromise)
if ($promiseOrValue instanceof \Generator && $promiseOrValue->valid()) {
$deferred = new Deferred();
// resolve value the generator is waiting for
resolve($promiseOrValue->current())->then(
function ($result) use ($promiseOrValue, $deferred) {
// resume generator
$promiseOrValue->send($result);
// try to resolve generator
resolve($promiseOrValue)->then(function () use ($deferred) {
$deferred->resolve();
});
}
);
return $deferred->promise();
}
if (!$promiseOrValue instanceof PromiseInterface) {
return new FulfilledPromise($promiseOrValue);
}
if ($promiseOrValue instanceof ExtendedPromiseInterface) {
return $promiseOrValue;
}
return new Promise(function ($resolve, $reject, $notify) use ($promiseOrValue) {
$promiseOrValue->then($resolve, $reject, $notify);
});
}
<?php
// working example - contained to React\Promise
require_once "vendor/autoload.php";
use React\Promise\Deferred;
use React\Promise;
$d = [new Deferred(), new Deferred(), new Deferred()];
$p = array_map(function ($v) { return $v->promise(); }, $d);
function make_generator(array $work)
{
for ($i=0; $i<count($work); $i++) {
echo $i . ": " . (yield $work[$i]) . "\n";
}
}
$gen = make_generator(array_merge($p, ["not-a-promise"]));
Promise\resolve($gen)->then(function() {
echo "end\n";
});
echo "start\n";
$d[0]->resolve("p1 resolved");
$d[1]->resolve("p2 resolved");
$d[2]->resolve("p3 resolved");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment