/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $hasValue = false; $hasAccumulation = false; $accumulation = $this->seed; $hasSeed = $this->seed !== null; return $observable->subscribe(new CallbackObserver(function ($x) use($observer, &$hasAccumulation, &$accumulation, &$hasSeed, &$hasValue) { $hasValue = true; if ($hasAccumulation) { $accumulation = call_user_func($this->tryCatch($this->accumulator), $accumulation, $x); } else { $accumulation = $hasSeed ? call_user_func($this->tryCatch($this->accumulator), $this->seed, $x) : $x; $hasAccumulation = true; } if ($accumulation instanceof \Exception) { $observer->onError($accumulation); return; } $observer->onNext($accumulation); }, function ($e) use($observer) { $observer->onError($e); }, function () use($observer, &$hasValue, &$hasSeed) { if (!$hasValue && $hasSeed) { $observer->onNext($this->seed); } $observer->onCompleted(); })); }
/** * @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) { $hasAccumulation = false; $accumulation = null; $hasValue = false; $cbObserver = new CallbackObserver(function ($x) use($observer, &$hasAccumulation, &$accumulation, &$hasValue) { $hasValue = true; try { if ($hasAccumulation) { $accumulation = call_user_func($this->accumulator, $accumulation, $x); } else { $accumulation = $this->hasSeed ? call_user_func($this->accumulator, $this->seed, $x) : $x; $hasAccumulation = true; } } catch (\Exception $e) { $observer->onError($e); } }, function ($e) use($observer) { $observer->onError($e); }, function () use($observer, &$hasAccumulation, &$accumulation, &$hasValue) { if ($hasValue) { $observer->onNext($accumulation); } else { $this->hasSeed && $observer->onNext($this->seed); } if (!$hasValue && !$this->hasSeed) { $observer->onError(new \Exception("Missing Seed and or Value")); } $observer->onCompleted(); }); return $observable->subscribe($cbObserver, $scheduler); }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $previousMax = null; $comparing = false; return $observable->subscribe(new CallbackObserver(function ($x) use(&$comparing, &$previousMax, $observer) { if (!$comparing) { $comparing = true; $previousMax = $x; return; } try { $result = call_user_func($this->comparer, $x, $previousMax); if ($result > 0) { $previousMax = $x; } } catch (\Exception $e) { $observer->onError($e); } }, [$observer, 'onError'], function () use(&$comparing, &$previousMax, $observer) { if ($comparing) { $observer->onNext($previousMax); $observer->onCompleted(); return; } $observer->onError(new \Exception("Empty")); }), $scheduler); }
public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $hasCurrentKey = false; $currentKey = null; return $observable->subscribe(new CallbackObserver(function ($value) use($observer, &$hasCurrentKey, &$currentKey) { $key = $value; if ($this->keySelector) { try { $key = call_user_func($this->keySelector, $value); } catch (\Exception $e) { return $observer->onError($e); } } $comparerEquals = null; if ($hasCurrentKey) { try { $comparerEquals = call_user_func($this->comparer, $currentKey, $key); } catch (\Exception $e) { return $observer->onError($e); } } if (!$hasCurrentKey || !$comparerEquals) { $hasCurrentKey = true; $currentKey = $key; $observer->onNext($value); } }, function ($e) use($observer) { $observer->onError($e); }, function () use($observer) { $observer->onCompleted(); })); }
/** * @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) { $cbObserver = new CallbackObserver(function ($x) use($observer) { try { $this->onEachObserver->onNext($x); } catch (\Exception $e) { return $observer->onError($e); } $observer->onNext($x); }, function ($err) use($observer) { try { $this->onEachObserver->onError($err); } catch (\Exception $e) { return $observer->onError($e); } $observer->onError($err); }, function () use($observer) { try { $this->onEachObserver->onCompleted(); } catch (\Exception $e) { return $observer->onError($e); } $observer->onCompleted(); }); return $observable->subscribe($cbObserver, $scheduler); }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $isOpen = false; /** @var DisposableInterface $otherDisposable */ $otherDisposable = $this->other->subscribe(new CallbackObserver(function ($x) use(&$isOpen, &$otherDisposable) { $isOpen = true; $otherDisposable->dispose(); }, function ($e) use($observer) { $observer->onError($e); }, function () use(&$otherDisposable) { $otherDisposable->dispose(); })); $sourceDisposable = $observable->subscribe(new CallbackObserver(function ($x) use($observer, &$isOpen) { if ($isOpen) { $observer->onNext($x); } }, function ($e) use($observer) { $observer->onError($e); }, function () use($observer, &$isOpen) { if ($isOpen) { $observer->onCompleted(); } })); return new CompositeDisposable([$otherDisposable, $sourceDisposable]); }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { array_unshift($this->sources, $observable); $this->numberOfSources = count($this->sources); $disposable = new CompositeDisposable(); $this->completesRemaining = $this->numberOfSources; for ($i = 0; $i < $this->numberOfSources; $i++) { $this->queues[$i] = new \SplQueue(); $this->completed[$i] = false; } for ($i = 0; $i < $this->numberOfSources; $i++) { $source = $this->sources[$i]; $cbObserver = new CallbackObserver(function ($x) use($i, $observer, $scheduler) { // if there is another item in the sequence after one of the other source // observables completes, we need to complete at this time to match the // behavior of RxJS if ($this->completesRemaining < $this->numberOfSources) { // check for completed and empty queues for ($j = 0; $j < $this->numberOfSources; $j++) { if ($this->completed[$j] && count($this->queues[$j]) === 0) { $observer->onCompleted(); return; } } } $this->queues[$i]->enqueue($x); for ($j = 0; $j < $this->numberOfSources; $j++) { if ($this->queues[$j]->isEmpty()) { return; } } $params = []; for ($j = 0; $j < $this->numberOfSources; $j++) { $params[] = $this->queues[$j]->dequeue(); } try { $observer->onNext(call_user_func_array($this->resultSelector, $params)); } catch (\Exception $e) { $observer->onError($e); } }, function ($e) use($observer) { $observer->onError($e); }, function () use($i, $observer) { $this->completesRemaining--; $this->completed[$i] = true; if ($this->completesRemaining === 0) { $observer->onCompleted(); } }); $subscription = $source->subscribe($cbObserver, $scheduler); $disposable->add($subscription); } return $disposable; }
/** * @param ObserverInterface $observer * @param SchedulerInterface|null $scheduler * @return \Rx\Disposable\CompositeDisposable|\Rx\DisposableInterface */ public function subscribe(ObserverInterface $observer, SchedulerInterface $scheduler = null) { $scheduler = $scheduler ?: new ImmediateScheduler(); $buffer = ''; $request = $this->client->request($this->method, $this->url, $this->headers, $this->protocolVersion); $request->on('response', function (Response $response) use(&$buffer, $observer, $request, $scheduler) { $response->on('data', function ($data, Response $response) use(&$buffer, $observer, $request, $scheduler) { try { //Http Errors if ($response->getCode() < 200 || $response->getCode() >= 400) { $error = new HttpResponseException($request, $response, $response->getReasonPhrase(), $response->getCode()); $observer->onError($error); return; } if ($this->bufferResults) { $buffer .= $data; } else { $data = $this->includeResponse ? [$data, $response, $request] : $data; $scheduler->schedule(function () use($observer, $data) { $observer->onNext($data); }); } } catch (\Exception $e) { $observer->onError($e); } }); $response->on('error', function ($e) use($observer) { $error = new \Exception($e); $observer->onError($error); }); $response->on('end', function ($end = null) use(&$buffer, $observer, $request, $response, $scheduler) { if ($this->bufferResults) { $data = $this->includeResponse ? [$buffer, $response, $request] : $buffer; $scheduler->schedule(function () use($observer, $data, $scheduler) { $observer->onNext($data); $scheduler->schedule(function () use($observer) { $observer->onCompleted(); }); }); return; } $scheduler->schedule(function () use($observer) { $observer->onCompleted(); }); }); }); $request->end($this->body); return new CallbackDisposable(function () use($request) { $request->close(); }); }
/** * @param ObserverInterface $observer * @param SchedulerInterface|null $scheduler * @return \Rx\Disposable\CompositeDisposable|\Rx\DisposableInterface */ public function subscribe(ObserverInterface $observer, SchedulerInterface $scheduler = null) { $scheduler = $scheduler ?: new ImmediateScheduler(); $key = 0; return $scheduler->scheduleRecursive(function ($reschedule) use(&$observer, &$key) { try { //HHVM requires you to call next() before current() if (defined('HHVM_VERSION')) { $this->items->next(); $key = $this->items->key(); } if (null === $key) { $observer->onCompleted(); return; } $current = $this->items->current(); $observer->onNext($current); if (!defined('HHVM_VERSION')) { $this->items->next(); $key = $this->items->key(); } $reschedule(); } catch (\Exception $e) { $observer->onError($e); } }); }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { if ($this->scheduler !== null) { $scheduler = $this->scheduler; } if ($scheduler === null) { throw new \Exception("You must use a scheduler that support non-zero delay."); } $lastScheduledTime = 0; $disposable = new CompositeDisposable(); $sourceDisposable = new EmptyDisposable(); $sourceDisposable = $observable->subscribe(new CallbackObserver(function ($x) use($scheduler, $observer, &$lastScheduledTime, $disposable) { $schedDisp = $scheduler->schedule(function () use($x, $observer, &$schedDisp, $disposable) { $observer->onNext($x); $disposable->remove($schedDisp); }, $this->delay); $disposable->add($schedDisp); }, function ($err) use($scheduler, $observer, &$lastScheduledTime, $disposable, &$sourceDisposable) { $disposable->remove($sourceDisposable); $sourceDisposable->dispose(); $observer->onError($err); }, function () use($scheduler, $observer, $disposable, &$sourceDisposable) { $disposable->remove($sourceDisposable); $sourceDisposable->dispose(); $schedDisp = $scheduler->schedule(function () use($observer, &$schedDisp, $disposable) { $observer->onCompleted(); $disposable->remove($schedDisp); }, $this->delay); $disposable->add($schedDisp); }), $scheduler); $disposable->add($sourceDisposable); return $disposable; }
/** * @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) { $group = new CompositeDisposable(); $isStopped = false; $sourceSubscription = new SingleAssignmentDisposable(); $group->add($sourceSubscription); $callbackObserver = new CallbackObserver(function (ObservableInterface $innerSource) use(&$group, &$isStopped, $observer, &$scheduler) { $innerSubscription = new SingleAssignmentDisposable(); $group->add($innerSubscription); $innerSubscription->setDisposable($innerSource->subscribe(new CallbackObserver(function ($nextValue) use($observer) { $observer->onNext($nextValue); }, function ($error) use($observer) { $observer->onError($error); }, function () use(&$group, &$innerSubscription, &$isStopped, $observer) { $group->remove($innerSubscription); if ($isStopped && $group->count() === 1) { $observer->onCompleted(); } }), $scheduler)); }, [$observer, 'onError'], function () use(&$group, &$isStopped, $observer) { $isStopped = true; if ($group->count() === 1) { $observer->onCompleted(); } }); $subscription = $this->sources->subscribe($callbackObserver, $scheduler); $sourceSubscription->setDisposable($subscription); return $group; }
public function subscribe(ObserverInterface $observer, SchedulerInterface $scheduler = null) { $scheduler = $scheduler ?: new ImmediateScheduler(); return $scheduler->schedule(function () use($observer) { $observer->onError($this->error); }); }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $onNext = function ($innerSource) use($observer, $scheduler) { $innerDisposable = new SingleAssignmentDisposable(); $id = ++$this->latest; $this->hasLatest = true; $this->innerSubscription->setDisposable($innerDisposable); $innerCallbackObserver = new CallbackObserver(function ($x) use($id, $observer) { if ($this->latest === $id) { $observer->onNext($x); } }, function ($e) use($id, $observer) { if ($this->latest === $id) { $observer->onError($e); } }, function () use($id, $observer) { if ($this->latest === $id) { $this->hasLatest = false; if ($this->isStopped) { $observer->onCompleted(); } } }); $innerSubscription = $innerSource->subscribe($innerCallbackObserver, $scheduler); $innerDisposable->setDisposable($innerSubscription); }; $callbackObserver = new CallbackObserver($onNext, [$observer, 'onError'], function () use($observer) { $this->isStopped = true; if (!$this->hasLatest) { $observer->onCompleted(); } }); $subscription = $observable->subscribe($callbackObserver, $scheduler); return new BinaryDisposable($subscription, $this->innerSubscription); }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { return $observable->subscribe(new CallbackObserver(function ($data) use($observer) { while (strlen($data) > 0) { $frame = $this->frame; $frame->addBuffer($data); $data = ""; if ($frame->isCoalesced()) { $result = $this->validator->validateFrame($frame, $this->previousFrame); if (0 !== $result) { $observer->onError(new WebsocketErrorException($result)); } $data = $frame->extractOverflow(); $frame->unMaskPayload(); $observer->onNext($frame); if ($frame->getOpcode() < 3) { $this->previousFrame = $this->frame; if ($frame->isFinal()) { $this->previousFrame = null; } } $this->frame = new Frame(); } } }, [$observer, 'onError'], [$observer, 'onCompleted'])); }
/** * @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]); }
/** * @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) { $selectObserver = new CallbackObserver(function ($nextValue) use($observer) { $value = null; try { $value = call_user_func($this->selector, $nextValue); } catch (\Exception $e) { $observer->onError($e); } $observer->onNext($value); }, function ($error) use($observer) { $observer->onError($error); }, function () use($observer) { $observer->onCompleted(); }); return $observable->subscribe($selectObserver, $scheduler); }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { return $observable->subscribe(new CallbackObserver(function ($x) { $this->arr[] = $x; }, function ($e) use($observer) { $observer->onError($e); }, function () use($observer) { $observer->onNext($this->arr); $observer->onCompleted(); })); }
/** * @param $socket * @param ObserverInterface $observer */ public function onConnected($socket, $observer) { $this->loop->removeWriteStream($socket); if (false === stream_socket_get_name($socket, true)) { $observer->onError(new ConnectionException('Connection refused')); $observer->onCompleted(); return; } $observer->onNext(new ConnectorEvent("/connector/connected", new Stream($socket, $this->loop), $this->labels)); //$observer->onCompleted(); }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $outerDisposable = new SerialDisposable(); $this->disposable->add($outerDisposable); $subscribe = function () use($outerDisposable, $observable, $observer, $scheduler, &$subscribe) { $this->sourceComplete = false; $outerSubscription = $observable->subscribe(new CallbackObserver([$observer, "onNext"], [$observer, "onError"], function () use($observer, &$subscribe, $outerDisposable) { $this->sourceComplete = true; if (!$this->repeat) { $observer->onCompleted(); return; } $outerDisposable->setDisposable(new EmptyDisposable()); $this->completions->onNext(++$this->count); }), $scheduler); $outerDisposable->setDisposable($outerSubscription); }; $notifierDisposable = $this->notifier->subscribe(new CallbackObserver(function () use(&$subscribe, $scheduler) { $subscribe(); }, function ($ex) use($observer) { $this->repeat = false; $observer->onError($ex); }, function () use($observer) { $this->repeat = false; if ($this->sourceComplete) { $observer->onCompleted(); } }), $scheduler); $this->disposable->add($notifierDisposable); try { $handled = call_user_func($this->notificationHandler, $this->completions->asObservable()); $handledDisposable = $handled->subscribe($this->notifier, $scheduler); $this->disposable->add($handledDisposable); } catch (\Exception $e) { $observer->onError($e); return new EmptyDisposable(); } $subscribe(); return $this->disposable; }
public function subscribe(ObserverInterface $observer, $scheduler = null) { $this->assertNotDisposed(); if (!$this->isStopped) { $this->observers[] = $observer; return new InnerSubscriptionDisposable($this, $observer); } if ($this->exception) { $observer->onError($this->exception); return new EmptyDisposable(); } $observer->onCompleted(); return new EmptyDisposable(); }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $this->q = []; return $observable->subscribe(new CallbackObserver(function ($x) use($observer) { $this->q[] = $x; if (count($this->q) > $this->count) { $observer->onNext(array_shift($this->q)); } }, function ($e) use($observer) { $observer->onError($e); }, function () use($observer) { $observer->onCompleted(); })); }
/** * @param ObserverInterface $observer * @param SchedulerInterface|null $scheduler * @return \Rx\Disposable\CompositeDisposable|\Rx\DisposableInterface */ public function subscribe(ObserverInterface $observer, SchedulerInterface $scheduler = null) { $scheduler = $scheduler ?: new ImmediateScheduler(); $key = 0; $defaultFn = function ($reschedule) use(&$observer, &$key) { try { if (null === $key) { $observer->onCompleted(); return; } $current = $this->items->current(); $observer->onNext($current); $this->items->next(); $key = $this->items->key(); $reschedule(); } catch (\Exception $e) { $observer->onError($e); } }; $hhvmFn = function ($reschedule) use(&$observer, &$key) { try { //HHVM requires you to call next() before current() $this->items->next(); $key = $this->items->key(); if (null === $key) { $observer->onCompleted(); return; } $current = $this->items->current(); $observer->onNext($current); $reschedule(); } catch (\Exception $e) { $observer->onError($e); } }; return $scheduler->scheduleRecursive(defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.11.0', 'lt') ? $hhvmFn : $defaultFn); }
protected function pollForOutput(ObserverInterface $observer, $previous) { $poll = new \ZMQPoll(); $read = $write = []; $poll->add($this->socket->getSocket(), \ZMQ::POLL_OUT); for ($i = 0; $i < 1000; $i += 1) { $events = $poll->poll($read, $write, 1); if ($events) { $observer->onNext($previous); return $observer->onCompleted(); } $this->loop->tick(); } return $observer->onError(new ConnectException("Socket is not answering")); }
/** * @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) { $selectObserver = new CallbackObserver(function ($nextValue) use($observer) { $shouldFire = false; try { $shouldFire = call_user_func($this->predicate, $nextValue); } catch (\Exception $e) { $observer->onError($e); } if ($shouldFire) { $observer->onNext($nextValue); } }, [$observer, 'onError'], [$observer, 'onCompleted']); return $observable->subscribe($selectObserver, $scheduler); }
/** * @param ObservableInterface $observable * @param ObserverInterface $observer * @param SchedulerInterface|null $scheduler * @return \Rx\DisposableInterface */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $onNext = function ($value) use($observer) { try { if (call_user_func($this->predicate, $value)) { $observer->onNext($value); } else { $observer->onCompleted(); } } catch (\Exception $e) { $observer->onError($e); } }; $callbackObserver = new CallbackObserver($onNext, [$observer, 'onError'], [$observer, 'onCompleted']); return $observable->subscribe($callbackObserver, $scheduler); }
/** * @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) { $callbackObserver = new CallbackObserver(function ($value) use($observer, $observable) { try { if ($this->isSkipping) { $this->isSkipping = call_user_func_array($this->predicate, [$value, $observable]); } if (!$this->isSkipping) { $observer->onNext($value); } } catch (\Exception $e) { $observer->onError($e); } }, [$observer, 'onError'], [$observer, 'onCompleted']); return $observable->subscribe($callbackObserver, $scheduler); }
public function subscribe(ObserverInterface $observer, $scheduler = null) { $this->stream->on('data', function ($data) use($observer) { $observer->onNext($data); }); $this->stream->on('error', function ($error) use($observer) { $ex = $error instanceof \Exception ? $error : new \Exception($error); $observer->onError($ex); }); $this->stream->on('close', function () use($observer) { $observer->onCompleted(); }); $disposable = parent::subscribe($observer, $scheduler); return new BinaryDisposable($disposable, new CallbackDisposable(function () use($observer) { $this->removeObserver($observer); $this->dispose(); })); }
/** * @param ObserverInterface $observer * @param \Rx\SchedulerInterface|null $scheduler * @return DisposableInterface */ public function subscribe(ObserverInterface $observer, \Rx\SchedulerInterface $scheduler = null) { $this->object->on($this->nextAction, function () use($observer) { $observer->onNext(func_get_args()); }); if ($this->errorAction) { $this->object->on($this->errorAction, function ($error = null) use($observer) { $ex = $error instanceof \Exception ? $error : new \Exception($error); $observer->onError($ex); }); } if ($this->completeAction) { $this->object->on($this->completeAction, function () use($observer) { $observer->onCompleted(); }); } return new EmptyDisposable(); }
/** * @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) { array_unshift($this->observables, $observable); $observables =& $this->observables; $compositeDisposable = new CompositeDisposable(); $hasValue = []; $values = array_keys($observables); $count = count($observables); $waitingToComplete = $count; $waitingForValues = $count; foreach ($observables as $key => $o) { $hasValue[$key] = false; $cbObserver = new CallbackObserver(function ($value) use($count, &$hasValue, $key, &$values, $observer, &$waitingForValues, &$waitingToComplete) { // If an observable has completed before it has emitted, we need to complete right away if ($waitingForValues > $waitingToComplete) { $observer->onCompleted(); return; } if ($waitingForValues > 0 && !$hasValue[$key]) { $hasValue[$key] = true; $waitingForValues--; } $values[$key] = $value; if ($waitingForValues === 0) { try { $result = call_user_func_array($this->resultSelector, $values); $observer->onNext($result); } catch (\Exception $e) { $observer->onError($e); } } }, [$observer, 'onError'], function () use(&$waitingToComplete, $observer) { $waitingToComplete--; if ($waitingToComplete === 0) { $observer->onCompleted(); } }); $subscription = $o->subscribe($cbObserver, $scheduler); $compositeDisposable->add($subscription); } return $compositeDisposable; }
/** * @inheritDoc */ public function __invoke(ObservableInterface $observable, ObserverInterface $observer, SchedulerInterface $scheduler = null) { $errors = new Subject(); $disposable = new CompositeDisposable(); $sourceDisposable = new EmptyDisposable(); $innerCompleted = false; $sourceError = false; try { $when = call_user_func($this->notificationHandler, $errors->asObservable()); } catch (\Exception $e) { $observer->onError($e); return; } $subscribeToSource = function () use($observer, $disposable, $observable, &$sourceError, $errors, &$sourceDisposable, $scheduler, &$innerCompleted) { $sourceError = false; $sourceDisposable = $observable->subscribe(new CallbackObserver([$observer, 'onNext'], function ($err) use(&$sourceError, $errors, $disposable, &$sourceDisposable, &$innerCompleted, $observer) { $sourceError = true; $disposable->remove($sourceDisposable); $sourceDisposable->dispose(); if ($innerCompleted) { $observer->onCompleted(); return; } $errors->onNext($err); }, [$observer, 'onCompleted']), $scheduler); $disposable->add($sourceDisposable); }; $whenDisposable = $when->subscribe(new CallbackObserver(function ($x) use($subscribeToSource, &$sourceError) { if ($sourceError) { $sourceError = false; $subscribeToSource(); } }, [$observer, 'onError'], function () use(&$innerCompleted, &$sourceError, $observer) { $innerCompleted = true; if ($sourceError) { $observer->onCompleted(); } }), $scheduler); $disposable->add($whenDisposable); $subscribeToSource(); return $disposable; }