2.2 KiB
Iterators
Iterators are the next level after promises. While promises resolve once and with one value, iterators allow a set of items to be consumed.
Iterator Consumption
Every iterator in Amp follows the Amp\Iterator
interface.
namespace Amp;
interface Iterator {
public function advance(): Promise;
public function getCurrent();
}
advance()
returns a Promise
and its resolution value tells whether there's an element to consume or not. If it resolves to true
, getCurrent()
can be used to consume the element at the current position, otherwise the iterator ended and there are no more values to consume. In case an exception happens, advance()
returns a failed promise and getCurrent()
throws the failure reason when called.
Simple Consumption Example
$iterator = foobar();
while (yield $iterator->advance()) {
$element = $iterator->getCurrent();
// do something with $element
}
Iterator Creation
Emitter
What Deferred
is for promises, is Emitter
for iterators. A library that returns an Iterator
for asynchronous consumption of an iterable result creates an Amp\Emitter
and returns the Iterator
using iterate()
. This ensures a consumer can only consume the iterator, but not emit values or complete the iterator.
emit()
emit()
emits a new value to the Iterator
, which can be consumed by a consumer. The emitted value is passed as first argument to emit()
. emit()
returns a Promise
that can be waited on before emitting new values. This allow emitting values just as fast as the consumer can consume them.
complete()
complete()
marks the Emitter
/ linked Iterator
as complete. No further emits are allowed after completing an Emitter
/ Iterator
.
Producer
Producer
is a simplified form of Emitter
that can be used when a single coroutine can emit all values.
Producer
accepts a callable
as first constructor parameter that gets run as a coroutine and passed an $emit
callable that can be used to emit values just like the emit()
method does in Emitter
.
Example
$iterator = new Producer(function (callable $emit) {
yield $emit(1);
yield $emit(new Delayed(500, 2));
yield $emit(3);
yield $emit(4);
});