Automattic\WooCommerce\Vendor\GraphQL\Executor\Promise\Adapter

SyncPromiseAdapter{}WC 1.0└─ PromiseAdapter

Allows changing order of field resolution even in sync environments (by leveraging queue of deferreds and promises).

No Hooks.

Usage

$SyncPromiseAdapter = new SyncPromiseAdapter();
// use class methods

Methods

  1. public all(iterable $promisesOrValues)
  2. public convertThenable($thenable)
  3. public create(callable $resolver)
  4. public createFulfilled($value = null)
  5. public createRejected(\Throwable $reason)
  6. public isThenable($value)
  7. public then(Promise $promise, ?callable $onFulfilled = null, ?callable $onRejected = null)
  8. public wait(Promise $promise)
  9. protected beforeWait(Promise $promise)
  10. protected onWait(Promise $promise)

SyncPromiseAdapter{} code WC 10.9.1

class SyncPromiseAdapter implements PromiseAdapter
{
    public function isThenable($value): bool
    {
        return $value instanceof SyncPromise;
    }

    /** @throws InvariantViolation */
    public function convertThenable($thenable): Promise
    {
        if (! $thenable instanceof SyncPromise) {
            // End-users should always use Deferred, not SyncPromise directly
            $deferredClass = Deferred::class;
            $safeThenable = Utils::printSafe($thenable);
            throw new InvariantViolation("Expected instance of {$deferredClass}, got {$safeThenable}.");
        }

        return new Promise($thenable, $this);
    }

    /** @throws InvariantViolation */
    public function then(Promise $promise, ?callable $onFulfilled = null, ?callable $onRejected = null): Promise
    {
        $syncPromise = $promise->adoptedPromise;
        assert($syncPromise instanceof SyncPromise);

        return new Promise($syncPromise->then($onFulfilled, $onRejected), $this);
    }

    /**
     * @throws \Exception
     * @throws InvariantViolation
     */
    public function create(callable $resolver): Promise
    {
        $syncPromise = new SyncPromise();

        try {
            $resolver(
                [$syncPromise, 'resolve'],
                [$syncPromise, 'reject']
            );
        } catch (\Throwable $e) {
            $syncPromise->reject($e);
        }

        return new Promise($syncPromise, $this);
    }

    /**
     * @throws \Exception
     * @throws InvariantViolation
     */
    public function createFulfilled($value = null): Promise
    {
        $syncPromise = new SyncPromise();

        return new Promise($syncPromise->resolve($value), $this);
    }

    /**
     * @throws \Exception
     * @throws InvariantViolation
     */
    public function createRejected(\Throwable $reason): Promise
    {
        $syncPromise = new SyncPromise();

        return new Promise($syncPromise->reject($reason), $this);
    }

    /**
     * @throws \Exception
     * @throws InvariantViolation
     */
    public function all(iterable $promisesOrValues): Promise
    {
        $all = new SyncPromise();

        $total = is_array($promisesOrValues)
            ? count($promisesOrValues)
            : iterator_count($promisesOrValues);
        $count = 0;
        $result = [];

        $resolveAllWhenFinished = function () use (&$count, &$total, $all, &$result): void {
            if ($count === $total) {
                $all->resolve($result);
            }
        };

        foreach ($promisesOrValues as $index => $promiseOrValue) {
            if ($promiseOrValue instanceof Promise) {
                $result[$index] = null;
                $promiseOrValue->then(
                    static function ($value) use (&$result, $index, &$count, &$resolveAllWhenFinished): void {
                        $result[$index] = $value;
                        ++$count;
                        $resolveAllWhenFinished();
                    },
                    [$all, 'reject']
                );
                continue;
            }

            $result[$index] = $promiseOrValue;
            ++$count;
        }

        $resolveAllWhenFinished();

        return new Promise($all, $this);
    }

    /**
     * Synchronously wait when promise completes.
     *
     * @throws InvariantViolation
     *
     * @return mixed
     */
    public function wait(Promise $promise)
    {
        $this->beforeWait($promise);

        $syncPromise = $promise->adoptedPromise;
        assert($syncPromise instanceof SyncPromise);

        while ($syncPromise->state === SyncPromise::PENDING) {
            SyncPromiseQueue::run();
            $this->onWait($promise);
        }

        if ($syncPromise->state === SyncPromise::FULFILLED) {
            return $syncPromise->result;
        }

        if ($syncPromise->state === SyncPromise::REJECTED) {
            throw $syncPromise->result;
        }

        throw new InvariantViolation('Could not resolve promise.');
    }

    /** Execute just before starting to run promise completion. */
    protected function beforeWait(Promise $promise): void {}

    /** Execute while running promise completion. */
    protected function onWait(Promise $promise): void {}
}