/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { if ($this->scheduler !== null) { $scheduler = $this->scheduler; } $innerDisp = new SerialDisposable(); $disp = $observable->subscribe(new CallbackObserver(function ($x) use($innerDisp, $observer, $scheduler) { $now = $scheduler->now(); if ($this->nextSend <= $now) { $innerDisp->setDisposable(new EmptyDisposable()); $observer->onNext($x); $this->nextSend = $now + $this->throttleTime - 1; return; } $newDisp = Observable::just($x)->delay($this->nextSend - $now)->subscribe(new CallbackObserver(function ($x) use($observer, $scheduler) { $observer->onNext($x); $this->nextSend = $scheduler->now() + $this->throttleTime - 1; if ($this->completed) { $observer->onCompleted(); } }, [$observer, 'onError']), $scheduler); $innerDisp->setDisposable($newDisp); }, function (\Exception $e) use($observer, $innerDisp) { $innerDisp->dispose(); $observer->onError($e); }, function () use($observer) { $this->completed = true; if ($this->nextSend === 0) { $observer->onCompleted(); } }), $scheduler); return new CompositeDisposable([$disp, $innerDisp]); }
/** * @test * */ public function promise_success() { $source = Observable::just(42); $promise = Promise::fromObservable($source); $promise->then(function ($value) { $this->assertEquals(42, $value); }, function () { $this->assertTrue(false); }); }
/** * @test */ public function connectable_observable_creation() { $y = 0; $s2 = new Subject(); $co2 = new ConnectableObservable(Observable::just(1), $s2); $co2->subscribe(new CallbackObserver(function ($x) use(&$y) { $y = $x; })); $this->assertNotEquals(1, $y); $co2->connect(); $this->assertEquals(1, $y); }
/** * @param \Rx\ObservableInterface $observable * @param \Rx\ObserverInterface $observer * @param \Rx\SchedulerInterface $scheduler * @return \Rx\DisposableInterface */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $buffer = ""; return $observable->defaultIfEmpty(Observable::just(null))->concat(Observable::just($this->delimiter))->concatMap(function ($x) use(&$buffer) { if ($x === null || $buffer === null) { $buffer = null; return Observable::emptyObservable(); } $items = explode($this->delimiter, $buffer . $x); $buffer = array_pop($items); return Observable::fromArray($items); })->subscribe($observer, $scheduler); }
function findSharePrice($symbol) { return Observable::just($symbol)->flatMap(function ($symbol) { return Observable::defer(function () use($symbol) { $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL, "http://finance.yahoo.com/webservice/v1/symbols/{$symbol}/usd/quote?format=json"); $result = curl_exec($ch); curl_close($ch); return Observable::just($result); }); })->map('json_decode')->map(function ($result) { return $result->list->resources[0]->resource->fields->price; }); }
<?php require_once __DIR__ . '/../bootstrap.php'; $source = \Rx\Observable::defer(function () { return \Rx\Observable::just(42); }); $subscription = $source->subscribe($stdoutObserver);
public function testRetryWhenInnerEmitsBeforeOuterError() { $xs = $this->createColdObservable([onNext(10, 1), onNext(20, 2), onNext(30, 3), onNext(40, 4), onCompleted(50)]); $results = $this->scheduler->startWithDispose(function () use($xs) { return $xs->retryWhen(function () { return Observable::just(1); }); }, 285); $this->assertMessages([onNext(210, 1), onNext(220, 2), onNext(230, 3), onNext(240, 4), onCompleted(250)], $results->getMessages()); $this->assertSubscriptions([subscribe(200, 250)], $xs->getSubscriptions()); }
<?php // Chapter 08 // Luis Atencio require_once '../functions/Combinators.php'; require_once '../../vendor/autoload.php'; require_once 'model/User.php'; require_once 'model/Account.php'; require_once 'common.php'; println('Example 0'); \Rx\Observable::just('Hello World!')->subscribe($stdoutObserver()); println('Example 1'); \Rx\Observable::fromArray([1, 2, 3, 4])->subscribe(new \Rx\Observer\CallbackObserver(function ($x) { echo 'Next: ', $x, PHP_EOL; }, function (Exception $ex) { echo 'Error: ', $ex->getMessage(), PHP_EOL; }, function () { echo 'Completed', PHP_EOL; })); println('Example 2 Reduce Map Filter with Curry'); $isEven = function ($num) { return $num % 2 === 0; }; $add = function ($x, $y) { return $x + $y; }; $raiseTo = function ($power, $num) { return pow($num, $power); }; $computeSquare = P::curry2($raiseTo)(2); \Rx\Observable::fromArray([1, 2, 3, 4])->filter($isEven)->map($computeSquare)->reduce($add, 0)->subscribe($stdoutObserver());
public function testCanCompleteInSubscribeAction() { $completed = false; $emitted = null; Observable::just(1)->skipUntil(Observable::just(1))->subscribeCallback(function ($x) use(&$emitted) { if ($emitted !== null) { $this->fail("emitted should be null"); } $emitted = $x; }, null, function () use(&$completed) { $completed = true; }); $this->assertTrue($completed); $this->assertEquals(1, $emitted); }
/** * @test */ public function concatMap_Then_Complete_Task() { $xs = Observable::fromArray([4, 3, 2, 1]); $results = []; $completed = false; $xs->concatMap(function ($x, $i) { return Observable::just($x + $i); })->subscribeCallback(function ($x) use(&$results) { $results[] = $x; }, function ($e) { $this->fail('Should not get an error'); }, function () use(&$completed) { $completed = true; }); $this->assertTrue($completed); $this->assertEquals([4, 4, 4, 4], $results); }
<?php require_once __DIR__ . '/../bootstrap.php'; $source = \Rx\Observable::just(2)->startWith(1); $subscription = $source->subscribe($stdoutObserver);
public function testConcatAllError() { $sources = Observable::fromArray([Observable::just(0), Observable::error(new \Exception()), Observable::just(2), Observable::just(3)]); $res = []; $error = false; $completed = false; $sources->concatAll()->subscribeCallback(function ($x) use(&$res) { $res[] = $x; }, function ($e) use(&$res, &$error) { $this->assertEquals([0], $res); $error = true; }, function () use(&$completed) { $completed = true; }); $this->assertTrue($error); $this->assertFalse($completed); }
/** * @param $host * @param int $maxRecursion * @return Observable\AnonymousObservable with ip address */ public function resolve($host, $maxRecursion = 50) { // Don't resolve IP if (filter_var($host, FILTER_VALIDATE_IP)) { return Observable::just($host); } // Caching if (array_key_exists($host, $this->cache)) { return Observable::just($this->cache[$host]); } return $this->lookup($host, 'A')->flatMap(function (Event $event) use($host, $maxRecursion) { $ip = Arrays::random($event->data["answers"]); if (!$ip) { throw new RemoteNotFoundException("Can't resolve {$host}"); } if (!filter_var($ip, FILTER_VALIDATE_IP)) { if ($maxRecursion <= 0) { throw new RecursionLimitException(); } return $this->resolve($ip, $maxRecursion - 1); } $this->cache[$host] = $ip; return Observable::just($ip); }); }
<?php require_once __DIR__ . '/../bootstrap.php'; $source = \Rx\Observable::just(4)->startWithArray([1, 2, 3]); $subscription = $source->subscribe($stdoutObserver);
/** * @test */ public function throttle_scheduler_overrides_subscribe_scheduler() { $scheduler = $this->createMock(SchedulerInterface::class); $scheduler->expects($this->any())->method('schedule')->willReturn(new EmptyDisposable()); Observable::just(1)->throttle(100, $scheduler)->subscribeCallback(null, null, null, new ImmediateScheduler()); }
<?php use React\EventLoop\Factory; use Rx\Observable; use Rx\Scheduler\EventLoopScheduler; require_once __DIR__ . '/../bootstrap.php'; $loop = Factory::create(); $scheduler = new EventLoopScheduler($loop); $times = [['value' => 0, 'time' => 100], ['value' => 1, 'time' => 600], ['value' => 2, 'time' => 400], ['value' => 3, 'time' => 900], ['value' => 4, 'time' => 200]]; // Delay each item by time and project value; $source = Observable::fromArray($times)->flatMap(function ($item) { return Observable::just($item['value'])->delay($item['time']); })->throttle(300); $subscription = $source->subscribe($stdoutObserver, $scheduler); $loop->run();
}, function () { echo 'Completed', PHP_EOL; })); println('Example 3 - Just and Map'); \Rx\Observable::just(\Model\User::all())->map(function ($results) { return count($results); })->subscribe($stdoutObserver()); println('Example 4 - Get all accounts of type SAVING'); \Rx\Observable::fromArray(\Model\Account::all())->filter(function (Account $account) { return $account->getType() === 'SAVINGS'; })->map(function (Account $savingsAccount) { return $savingsAccount->getBalance(); })->subscribe($stdoutObserver()); println('Withdraw 1000 from Luis SAVINGS account'); $id = 1; Observable::just($id)->map(function ($userId) { return User::find($userId); })->doOnNext(function (User $user) { printf("Found user: %s \n", $user->getEmail()); })->flatMap(function (User $user) { return Observable::fromArray(Account::query('user_id', $user->getId())); })->takeWhile(function (Account $account) { return $account->getType() === 'SAVINGS'; })->doOnNext(function (Account $account) { printf("Found savings account. Current balance: %d \n", $account->getBalance()); })->map(function (Account $account) { return $account->withdraw(1000)->save(); })->subscribe(new Observer\CallbackObserver(function ($account) { printf("New account balance: %d \n", $account->getBalance()); }, function (Exception $ex) { print 'Error: ' . $ex->getMessage();
<?php require_once __DIR__ . '/../bootstrap.php'; $source1 = \Rx\Observable::just(42); $source2 = \Rx\Observable::just(56); $source = \Rx\Observable::emptyObservable()->concat($source1)->concat($source2); $subscription = $source->subscribe($stdoutObserver);
<?php require_once __DIR__ . '/../bootstrap.php'; $source = \Rx\Observable::just(42); $subscription = $source->subscribe($stdoutObserver);
public function testWithImmediateSchedulerWithRecursion() { $completed = false; $emitted = null; Observable::range(0, 10)->flatMap(function ($x) use(&$count) { if (++$count < 2) { return Observable::error(new \Exception("Something")); } return Observable::just(42); })->retry(3)->take(1)->subscribe(new CallbackObserver(function ($x) use(&$emitted) { $emitted = $x; }, null, function () use(&$completed) { $completed = true; }), new ImmediateScheduler()); $this->assertTrue($completed); $this->assertEquals(42, $emitted); }
<?php require __DIR__ . "/../../vendor/autoload.php"; $loop = \EventLoop\EventLoop::getLoop(); $rabbit = new \Rxnet\RabbitMq\RabbitMq('rabbit://*****:*****@127.0.0.1:5672/', new \Rxnet\Serializer\Serialize()); // Wait for rabbit to be up (lazy way) \Rxnet\awaitOnce($rabbit->connect()); $queue = $rabbit->queue('test_queue', []); $exchange = $rabbit->exchange('amq.direct'); // Start an observable sequence $queue->create($queue::DURABLE)->zip([$exchange->create($exchange::TYPE_DIRECT, [$exchange::DURABLE, $exchange::AUTO_DELETE]), $queue->bind('/routing/key', 'amq.direct')])->doOnNext(function () { echo "Exchange, and queue are created and bounded\n"; })->subscribeCallback(function () use($exchange, $loop) { $done = 0; $start = microtime(true); $repeat = 10000; // produce this array to my queue \Rx\Observable::just(['id' => 2, 'foo' => 'bar'])->flatMap(function ($data) use($exchange) { // Rabbit will handle serialize and unserialize return $exchange->produce($data, '/routing/key'); })->repeat($repeat)->subscribeCallback(function () use(&$done) { $done++; }, null, function () use(&$done, $start, $loop) { echo number_format($done) . " lines produced in " . (microtime(true) - $start) . "ms\n"; $loop->stop(); }); }); $loop->run();