Skip to content

Deferred and Promise objects

Greg Bowler edited this page May 4, 2026 · 3 revisions

This package keeps asynchronous work and asynchronous results separate:

  • Deferred manages the work.
  • Promise represents the eventual outcome.

That separation is the main idea to keep in mind while reading the rest of the API.

Deferred

A Deferred is the object we control directly. It has three main responsibilities:

  • Store one or more process callbacks.
  • Expose a Promise through getPromise().
  • Settle that promise later with resolve() or reject().

The process list is available through getProcessList(), and isActive() tells us whether the deferred task still has work left to do.

use GT\Promise\Deferred;

$deferred = new Deferred();
$deferred->addProcess(function() use ($deferred) {
	$deferred->resolve("Done");
});

Concrete Deferred objects also provide onComplete(), which can be useful when you want to run local cleanup code after the deferred finishes. That helper is available on the class itself rather than on DeferredInterface.

Promise

A Promise is what we return to the caller. It exposes:

  • then() for resolved values
  • catch() for rejections
  • finally() for code that should run in either case
  • getState() to inspect whether the promise is PENDING, RESOLVED, or REJECTED

The promise does not know how to do the work itself. It only reacts when the paired deferred settles it.

Returning promises from your own classes

This is the usual pattern when building on top of this package:

use GT\Promise\Deferred;
use GT\Promise\PromiseInterface;

class ExampleJob {
	private Deferred $deferred;
	private array $items;

	public function __construct(array $items) {
		$this->items = $items;
	}

	public function start():PromiseInterface {
		$this->deferred = new Deferred(fn() => $this->tick());
		return $this->deferred->getPromise();
	}

	private function tick():void {
		if($this->items) {
			array_shift($this->items);
			return;
		}

		$this->deferred->resolve("All items processed");
	}
}

The calling code only needs the promise:

$job = new ExampleJob(["a", "b", "c"]);
$job->start()->then(function(string $message) {
	echo $message, PHP_EOL;
});

The event loop, runner, or timer that calls tick() can stay elsewhere in the application.


Next: Chained promises.

Clone this wiki locally