Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Promise Laravel Package

php-standard-library/promise

Lightweight PHP promise implementation for composing and coordinating async-style workflows. Create, resolve, reject, and chain promises with then/catch-style handlers, useful for deferred results, task pipelines, and bridging callback-based APIs into a cleaner flow.

Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require php-standard-library/promise
    

    Add to composer.json under require if not using Composer globally.

  2. First Use Case: Replace a nested callback with a Promise chain for a simple async operation (e.g., HTTP request, DB query):

    use PhpStandardLibrary\Promise\Promise;
    
    $promise = new Promise(function ($resolve, $reject) {
        // Simulate async work (e.g., Guzzle HTTP request)
        $response = file_get_contents('https://api.example.com/data');
        if ($response === false) {
            $reject(new RuntimeException('Request failed'));
        } else {
            $resolve(json_decode($response, true));
        }
    });
    
    $promise->then(
        function ($data) {
            // Handle success
            return $data['result'];
        }
    )->catch(
        function (Throwable $e) {
            // Handle error
            error_log($e->getMessage());
        }
    );
    
  3. Where to Look First:

    • Promise class: Core class for creating and chaining promises.
    • Promise\all()/Promise\race(): Static combinators for orchestrating multiple promises.
    • Promise\defer(): Helper for creating deferred promises (resolved/rejected later).
    • Documentation: Check for examples in tests/ or examples/ directories (if provided).

Implementation Patterns

Core Workflows

  1. Deferred Resolution: Use Promise\defer() to create a promise resolved/rejected later (e.g., in event handlers):

    $deferred = Promise\defer();
    // Later, in an event listener:
    $deferred->resolve($data);
    // Or:
    $deferred->reject(new Exception('Failed'));
    
  2. Chaining Async Operations: Chain .then() for sequential async work (e.g., fetch → process → save):

    $promise
        ->then(fn($data) => $this->processData($data))
        ->then(fn($processed) => $this->saveToDb($processed));
    
  3. Parallel Execution with all(): Run multiple promises concurrently and wait for all to complete:

    $promises = [
        $this->fetchUserData($userId),
        $this->fetchOrderHistory($userId),
    ];
    Promise\all($promises)->then(function ($results) {
        $userData = $results[0];
        $orderHistory = $results[1];
        // Combine results...
    });
    
  4. Error Handling: Use .catch() for global error handling or .then() with rejection checks:

    $promise->then(
        fn($data) => $data,
        fn(Throwable $e) => error_log($e)
    );
    
  5. Integration with Laravel:

    • Queues: Wrap queue jobs in promises to chain post-processing:
      $job = Bus::dispatch(new ProcessDataJob($data));
      Promise\fromCallable([$job, 'handle'])
          ->then(fn() => $this->notifyUser());
      
    • HTTP Clients: Replace Guzzle’s callbacks with promises:
      $promise = new Promise(function ($resolve) use ($client) {
          $client->getAsync('...')->then(fn($response) => $resolve($response->getBody()));
      });
      
  6. Custom Promise Creators: Extend the library by creating helper methods for your domain:

    function fetchWithRetry($url, int $retries = 3): Promise {
        return new Promise(function ($resolve, $reject) use ($url, $retries) {
            // Retry logic...
        });
    }
    

Gotchas and Tips

Pitfalls

  1. No Event Loop:

    • This library is not an event loop (e.g., no Promise::wait()). Use Promise\all() or Promise\race() to block until completion.
    • For non-blocking apps, integrate with a loop like ReactPHP or Laravel’s queue system.
  2. Memory Leaks:

    • Unresolved promises can leak memory. Always resolve/reject promises or chain .finally() to clean up:
      $promise->finally(fn() => $this->cleanup());
      
  3. Callback Order:

    • .then() handlers run in registration order, not execution order. Avoid relying on order for side effects.
  4. Rejection Handling:

    • Uncaught rejections do not throw exceptions by default. Always attach .catch() or handle rejections explicitly:
      $promise->then(fn($data) => $data)->catch(fn($e) => null);
      
  5. Thread Safety:

    • Promises are not thread-safe. Avoid resolving/rejecting from multiple threads (e.g., in parallel workers).

Debugging

  1. State Inspection: Use Promise::isPending(), Promise::isFulfilled(), or Promise::isRejected() to debug stuck promises:

    if ($promise->isPending()) {
        error_log('Promise is still pending!');
    }
    
  2. Stack Traces: Wrap rejections in exceptions with stack traces for debugging:

    $promise->catch(function (Throwable $e) {
        throw new RuntimeException('Failed to process', 0, $e);
    });
    
  3. Logging: Log promise states for observability:

    $promise->then(fn() => logger()->info('Resolved!'))
            ->catch(fn($e) => logger()->error($e));
    

Tips

  1. Compose with Laravel:

    • Use Promise with Laravel’s Bus or Queue for async workflows:
      $job = Bus::dispatch(new AsyncJob());
      Promise\fromCallable([$job, 'handle'])->then(...);
      
  2. Type Safety: Use PHP 8’s return types for better IDE support:

    function fetchData(): Promise {
        return new Promise(fn($resolve) => $resolve(['data']));
    }
    
  3. Testing: Mock promises in tests with Promise\resolve() or Promise\reject():

    $mockPromise = Promise\resolve(['test']);
    $this->app->instance(Promise::class, $mockPromise);
    
  4. Performance:

    • Prefer Promise\all() over sequential .then() chains for parallel tasks.
    • Avoid creating promises in hot loops (e.g., inside foreach).
  5. Extension Points:

    • Implement PhpStandardLibrary\Promise\PromiseInterface for custom promise types.
    • Extend Promise to add domain-specific methods (e.g., Promise::retry()).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport