1
0
mirror of https://github.com/danog/amp.git synced 2024-12-15 10:57:19 +01:00
amp/lib/Resolver.php

80 lines
2.2 KiB
PHP
Raw Normal View History

2014-09-22 22:47:48 +02:00
<?php
2014-09-23 04:38:32 +02:00
namespace Amp;
2014-09-22 22:47:48 +02:00
class Resolver {
private $reactor;
/**
2014-09-23 04:38:32 +02:00
* @param \Amp\Reactor $reactor
2014-09-22 22:47:48 +02:00
*/
public function __construct(Reactor $reactor = null) {
2014-09-23 04:38:32 +02:00
$this->reactor = $reactor ?: \Amp\reactor();
2014-09-22 22:47:48 +02:00
}
/**
* A co-routine to resolve Generators
*
* Returns a promise that will resolve when the generator completes. The final value yielded by
* the generator is used to resolve the returned promise on success.
*
* Generators are expected to yield Promise instances and/or other Generator instances.
*
* Example:
*
* $generator = function() {
* $a = (yield 2);
* $b = (yield new Success(21));
* yield $a * $b;
* };
*
* resolve($generator())->when(function($error, $result) {
* var_dump($result); // int(42)
* });
*
* @param \Generator
2014-09-23 04:38:32 +02:00
* @return \Amp\Promise
2014-09-22 22:47:48 +02:00
*/
public function resolve(\Generator $gen) {
$future = new Future($this->reactor);
$this->advance($gen, $future);
return $future;
}
private function advance(\Generator $gen, Future $future, $previousResult = null) {
try {
$current = $gen->current();
} catch (\Exception $e) {
return $future->fail($e);
}
if ($current instanceof Promise) {
$current->when(function($error, $result) use ($gen, $future) {
$this->send($gen, $future, $error, $result);
});
} elseif ($current instanceof \Generator) {
$this->resolve($current)->when(function($error, $result) use ($gen, $future) {
$this->send($gen, $future, $error, $result);
});
} elseif ($gen->valid()) {
$this->send($gen, $future, $error = null, $current);
} else {
$future->succeed($previousResult);
}
}
private function send(\Generator $gen, Future $future, \Exception $error = null, $result = null) {
try {
if ($error) {
$gen->throw($error);
} else {
$gen->send($result);
}
$this->advance($gen, $future, $result);
} catch (\Exception $error) {
$future->fail($error);
}
}
}