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']);
             }
         });
     }
 }
Example #4
0
 /** @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);
 }
Example #5
0
/**
 * 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;
}
Example #6
0
 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;
 }
Example #7
0
 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);
         }
     });
 }
Example #8
0
 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());
 }
Example #9
0
 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;
 }
Example #10
0
 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();
     }
 }
Example #11
0
 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;
 }
Example #12
0
 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;
 }
Example #13
0
 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);
 }
Example #14
0
 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);
 }
Example #15
0
 /**
  * @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();
             }
         };
     });
 }
Example #16
0
 /**
  * @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;
});
Example #18
0
/**
 * 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();
}
Example #19
0
 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);
 }
Example #20
0
 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);
 }
Example #22
0
 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());
     }
 }
Example #23
0
 /**
  * {@inheritdoc}
  */
 public function cancel($reason = null)
 {
     $this->pause();
     parent::cancel($reason);
 }
Example #24
0
/**
 * 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;
}