public function run(Promise &$promise) { $urlInfo = parse_url($this->url); $timeout = $this->timeout; if (!isset($urlInfo['port'])) { $urlInfo['port'] = 80; } $cli = new \swoole_http_client($urlInfo['host'], $urlInfo['port']); $cli->set(array('timeout' => $timeout, 'keepalive' => 0)); $cli->on("error", function ($cli) use(&$promise) { Timer::del($cli->sock); $promise->accept(['http_data' => null, 'http_error' => 'Connect error']); }); $cli->on("close", function ($cli) use(&$promise) { }); $cli->execute($this->url, function ($cli) use(&$promise) { Timer::del($cli->sock); $cli->isDone = true; $promise->accept(['http_data' => $cli->body]); }); $cli->isConnected = false; if (!$cli->errCode) { Timer::add($cli->sock, $this->timeout, function () use($cli, &$promise) { @$cli->close(); if ($cli->isConnected) { $promise->accept(['http_data' => null, 'http_error' => 'Http client read timeout']); } else { $promise->accept(['http_data' => null, 'http_error' => 'Http client connect timeout']); } }); } }
public function run(Promise &$promise) { $data = json_encode($promise->getData()); $this->response->end($data); //echo "Mem: ",\memory_get_usage() / 1024,"k \n"; $promise->accept(); }
public function run(Promise &$promise) { $cli = new \swoole_client(SWOOLE_TCP, SWOOLE_SOCK_ASYNC); $urlInfo = parse_url($this->url); $timeout = $this->timeout; if (!isset($urlInfo['port'])) { $urlInfo['port'] = 80; } $httpParser = new \HttpParser(); $cli->on("connect", function ($cli) use($urlInfo, &$timeout, &$promise) { $cli->isConnected = true; $host = $urlInfo['host']; if ($urlInfo['port']) { $host .= ':' . $urlInfo['port']; } $req = array(); $req[] = "GET {$this->url} HTTP/1.1\r\n"; $req[] = "User-Agent: PHP swAsync\r\n"; $req[] = "Host:{$host}\r\n"; $req[] = "Connection:close\r\n"; $req[] = "\r\n"; $req = implode('', $req); $cli->send($req); }); $cli->on("receive", function ($cli, $data = "") use(&$httpParser, &$promise) { $ret = $httpParser->execute($data); if ($ret !== false) { Timer::del($cli->sock); $cli->isDone = true; if ($cli->isConnected()) { $cli->close(); } $promise->accept(['http_data' => $ret]); } }); $cli->on("error", function ($cli) use(&$promise) { Timer::del($cli->sock); $promise->accept(['http_data' => null, 'http_error' => 'Connect error']); }); $cli->on("close", function ($cli) use(&$promise) { }); if ($this->proxy) { $cli->connect($this->proxy['host'], $this->proxy['port'], 0.05); } else { $cli->connect($urlInfo['host'], $urlInfo['port'], 0.05); } $cli->isConnected = false; if (!$cli->errCode) { Timer::add($cli->sock, $this->timeout, function () use($cli, &$promise) { @$cli->close(); if ($cli->isConnected) { $promise->accept(['http_data' => null, 'http_error' => 'Http client read timeout']); } else { $promise->accept(['http_data' => null, 'http_error' => 'Http client connect timeout']); } }); } }
/** @test */ public function shouldRejectIfResolverThrowsException() { $exception = new \Exception('foo'); $promise = new Promise(function () use($exception) { throw $exception; }); $mock = $this->createCallableMock(); $mock->expects($this->once())->method('__invoke')->with($this->identicalTo($exception)); $promise->then($this->expectCallableNever(), $mock); }
/** * Adds a function to run in the task queue when it is next `run()` and returns * a promise that is fulfilled or rejected with the result. * * @param callable $task Task function to run. * * @return PromiseInterface */ function task(callable $task) { $queue = queue(); $promise = new Promise([$queue, 'run']); $queue->add(function () use($task, $promise) { try { $promise->resolve($task()); } catch (\Exception $e) { $promise->reject($e); } }); return $promise; }
private function checkIfFinished() { if (!$this->pending && !$this->iterable->valid()) { // Resolve the promise if there's nothing left to do. $this->aggregate->resolve(null); return true; } return false; }
public function __construct(Promise $promise) { $this->valids[$this->readPos] = new Deferred(); $promise->watch(function ($data) { $curPos = $this->writePos; $this->writePos++; $this->valids[] = new Deferred(); $this->values[$curPos] = $data; $this->valids[$curPos]->succeed(true); }); $promise->when(function ($error, $result) { if ($error) { $this->valids[$this->writePos]->fail($error); } else { $curPos = $this->writePos; $this->values[$this->writePos++] = $result; $this->valids[$curPos]->succeed(false); } }); }
public function testPromiseThen__ThenRejectedByPromiseButResolved() { $result = new Client($this->store); $promise1 = new Client($this->store); $this->object = $promise1->then(null, function ($reason) { return $reason->getMessage() . ' was resolved'; }); $promise1->reject($result); $this->assertEquals($result->getId() . ' was resolved', $this->object->wait(false)); $this->assertEquals(PromiseInterface::FULFILLED, $this->object->getState()); }
public function then(callable $onFulfilled = null, callable $onRejected = null) { // Return itself if there is no onFulfilled function. if (!$onFulfilled) { return $this; } $queue = queue(); $p = new Promise([$queue, 'run']); $value = $this->value; $queue->add(static function () use($p, $value, $onFulfilled) { if ($p->getState() === self::PENDING) { try { $p->resolve($onFulfilled($value)); } catch (\Exception $e) { $p->reject($e); } } }); return $p; }
private function step($idx) { // If the promise was already resolved, then ignore this step. if ($this->aggregate->getState() !== PromiseInterface::PENDING) { return; } unset($this->pending[$idx]); if (!$this->checkIfFinished()) { // Add more pending promises if possible. $this->refillPending(); } }
public function then(callable $onFulfilled = null, callable $onRejected = null) { // If there's no onRejected callback then just return self. if (!$onRejected) { return $this; } $queue = queue(); $reason = $this->reason; $p = new Promise([$queue, 'run']); $queue->add(static function () use($p, $reason, $onRejected) { if ($p->getState() === self::PENDING) { try { // Return a resolved promise if onRejected does not throw. $p->resolve($onRejected($reason)); } catch (\Throwable $e) { // onRejected threw, so return a rejected promise. $p->reject($e); } catch (\Exception $e) { // onRejected threw, so return a rejected promise. $p->reject($e); } } }); return $p; }
public static function create($sthGroup) { if (!is_array($sthGroup)) { throw new \Exception('asset is_array($sthGroup)'); } $promiseGroup = new self(); foreach ($sthGroup as $sth) { $promise = Promise::create($sth); $promise->nextPromise = $promiseGroup; $promiseGroup->subPromiseArray[] = $promise; } return $promiseGroup; }
public function resolveWith(Promise $context) { $context->resolve(); $this->args = func_get_args() and array_shift($this->args); $this->_execute($this->done, $context); $this->_execute($this->always, $context); }
public function testPromiseAsMonad() { $result = Promise::resolve(2)->bind(function ($value) { return Promise::resolve(3)->bind(function ($value2) use($value) { return $value + $value2; }); }); $this->assertEquals('Promise(5)', (string) $result); }
/** * @param \Generator $generator */ public function __construct(Generator $generator) { $this->generator = $generator; parent::__construct(function (callable $resolve, callable $reject) { /** * @param mixed $value The value to send to the generator. * @param \Throwable|null $exception Exception object to be thrown into the generator if not null. */ $this->worker = function ($value = null, Throwable $exception = null) use($resolve, $reject) { if ($this->paused) { // If paused, mark coroutine as ready to resume. $this->ready = true; return; } try { if ($this->initial) { // Get result of first yield statement. $this->initial = false; $this->current = $this->generator->current(); } elseif (null !== $exception) { // Throw exception at current execution point. $this->current = $this->generator->throw($exception); } else { // Send the new value and execute to next yield statement. $this->current = $this->generator->send($value); } if (!$this->generator->valid()) { $resolve($this->generator->getReturn()); $this->close(); return; } if ($this->current instanceof Generator) { $this->current = new self($this->current); } if ($this->current instanceof PromiseInterface) { $this->current->done($this->worker, $this->capture); } else { Loop\queue($this->worker, $this->current); } } catch (Throwable $exception) { $reject($exception); $this->close(); } }; /** * @param \Throwable $exception Exception to be thrown into the generator. */ $this->capture = function (Throwable $exception) { if (null !== $this->worker) { // Coroutine may have been closed. ($this->worker)(null, $exception); } }; Loop\queue($this->worker); return function (Throwable $exception) { try { $current = $this->generator->current(); // Get last yielded value. while ($this->generator->valid()) { if ($current instanceof PromiseInterface) { $current->cancel($exception); } $current = $this->generator->throw($exception); } } finally { $this->close(); } }; }); }
/** * @param Promise $subPromise * @param callable $callBack * @return void */ private function invokeCallback(Promise $subPromise, callable $callBack = null) { nextTick(function () use($callBack, $subPromise) { if (is_callable($callBack)) { try { $result = $callBack($this->value); if ($result instanceof self) { $result->then([$subPromise, 'fulfill'], [$subPromise, 'reject']); } else { $subPromise->fulfill($result); } } catch (\Exception $e) { // If the event handler threw an exception, we need to make sure that // the chained promise is rejected as well. $subPromise->reject($e); } } else { if ($this->state === self::FULFILLED) { $subPromise->fulfill($this->value); } else { $subPromise->reject($this->value); } } }); }
* @param Closure $closure */ public function __construct(Closure $closure) { $this->closure = $closure; $this->start(); } public function run() { $this->synchronized(function () { $closure = $this->closure; $this->result = $closure(); $this->notify(); }); } public function then(callable $callback) { return $this->synchronized(function () use($callback) { if (!$this->result) { $this->wait(); } $callback($this->result); }); } } $promise = new Promise(function () { return file_get_contents('http://google.fr'); }); $promise->then(function ($results) { echo $results; });
/** * Create an artificial timeout for any Promise. * * If the timeout expires before the promise is resolved, the returned promise fails with an instance of * \Amp\TimeoutException. * * @param \Interop\Async\Promise $promise * @param int $timeout Timeout in milliseconds. * * @return \Interop\Async\Promise */ function timeout(Promise $promise, int $timeout) : Promise { $deferred = new Deferred(); $resolved = false; $watcher = Loop::delay($timeout, function () use(&$resolved, $deferred) { if (!$resolved) { $resolved = true; $deferred->fail(new TimeoutException()); } }); $promise->when(function () use(&$resolved, $promise, $deferred, $watcher) { Loop::cancel($watcher); if ($resolved) { return; } $resolved = true; $deferred->resolve($promise); }); return $deferred->promise(); }
function testAllReject() { $promise1 = new Promise(); $promise2 = new Promise(); $finalValue = 0; Promise::all([$promise1, $promise2])->then(function ($value) use(&$finalValue) { $finalValue = 'foo'; return 'test'; }, function ($value) use(&$finalValue) { $finalValue = $value; }); $promise1->reject(1); $this->assertEquals(1, $finalValue); $promise2->reject(2); $this->assertEquals(1, $finalValue); }
public function manage(Promise $promise, Thenable $thenable) { return new Promise([$this, $promise->getWorker()], $thenable); }
function testResolveToLastYieldPromise() { $ok = false; $promise = new Promise(); coroutine(function () use($promise) { (yield 'fail'); (yield $promise); $hello = 'hi'; })->then(function ($value) use(&$ok) { $ok = $value; $this->fail($reason); }); $promise->fulfill('omg it worked'); Loop\run(); $this->assertEquals('omg it worked', $ok); }
function testWaitRejectedNonScalar() { $promise = new Promise(); Loop\nextTick(function () use($promise) { $promise->reject([]); }); try { $promise->wait(); $this->fail('We did not get the expected exception'); } catch (\Exception $e) { $this->assertInstanceOf('Exception', $e); $this->assertEquals('Promise was rejected with reason of type: array', $e->getMessage()); } }
/** * {@inheritdoc} */ public function cancel($reason = null) { $this->pause(); parent::cancel($reason); }
/** * Block script execution indefinitely until the specified Promise resolves * * In the event of promise failure this method will throw the exception responsible for the failure. * Otherwise the promise's resolved value is returned. * * @param \Amp\Promise $promise The promise on which to wait * @throws \Exception if the promise fails * @return mixed Returns the eventual resolution result for the specified promise */ function wait(Promise $promise) { $isWaiting = true; $resolvedError = null; $resolvedResult = null; $promise->when(function ($error, $result) use(&$isWaiting, &$resolvedError, &$resolvedResult) { $isWaiting = false; $resolvedError = $error; $resolvedResult = $result; }); while ($isWaiting) { tick(); } if ($resolvedError) { throw $resolvedError; } return $resolvedResult; }