2.6 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);
});
fromIterable
Iterators can also be created from ordinary PHP arrays or Traversable
instances, which is mainly useful in tests, but might also be used for the same reasons as Success
and Failure
.
function fromIterable($iterable, int $delay = 0) { ... }
$delay
allows adding a delay between each emission.