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

Promises Laravel Package

guzzlehttp/promises

Promises/A+ implementation for PHP with iterative, stack-safe chaining. Provides synchronous wait(), cancellation, interop with any thenable, and coroutine-style async/await via Coroutine::of(). Includes Promise, FulfilledPromise, and RejectedPromise.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require guzzlehttp/promises
    

    Ensure your composer.json targets PHP 7.2.5+ (for v2.x) or 5.5+ (for v1.x).

  2. First Use Case: Replace callback hell in async operations (e.g., HTTP requests, DB queries) with promises. Example: Wrap a slow function in a promise:

    use GuzzleHttp\Promise\Promise;
    
    $promise = new Promise(function () {
        // Simulate async work (e.g., API call)
        sleep(1);
        return "Result";
    });
    
    $promise->then(function ($result) {
        echo "Async result: " . $result; // Outputs after 1 second
    });
    
  3. Where to Look First:


Implementation Patterns

Core Workflows

1. Chaining Async Operations

Use then() to chain dependent async tasks (e.g., sequential API calls):

$promise = new Promise(function () {
    return fetchUserData();
});

$promise->then(function ($user) {
    return fetchUserPosts($user->id);
})->then(function ($posts) {
    return processPosts($posts);
})->then(function ($result) {
    saveToDatabase($result);
});

2. Error Handling

Use then(null, $onRejected) or otherwise() for centralized error handling:

$promise->then(null, function ($reason) {
    logError($reason);
    return fallbackData();
});

3. Parallel Execution

Combine multiple promises with all() (from GuzzleHttp\Promise\Utils):

use GuzzleHttp\Promise\Utils;

$promises = [
    fetchData('users'),
    fetchData('posts'),
    fetchData('comments')
];

Utils::all($promises)->then(function ($results) {
    // $results = [userData, postData, commentData]
});

4. Cancellation

Cancel pending promises (e.g., timeout or user request):

$promise = new Promise(
    function () { /* Long-running task */ },
    function () { /* Cleanup (e.g., close DB connection) */ }
);

$promise->cancel(); // Triggers cleanup

5. Synchronous Unwrapping

Use wait() for blocking operations (e.g., CLI scripts):

$result = $promise->wait(); // Blocks until resolved

Integration Tips

  • Guzzle HTTP Client: Leverage GuzzleHttp\Client with promises for async requests:

    $client = new \GuzzleHttp\Client();
    $promise = $client->requestAsync('GET', 'https://api.example.com');
    $promise->then(function ($response) {
        return $response->getBody();
    });
    
  • Event Loop Integration: Run the task queue in a loop (e.g., ReactPHP):

    $queue = \GuzzleHttp\Promise\Utils::queue();
    $loop->addPeriodicTimer(0.01, [$queue, 'run']);
    
  • Coroutines: Use Coroutine::of() for async/await-style code:

    $result = \GuzzleHttp\Promise\Coroutine::of(function () {
        $data = yield fetchData();
        return process($data);
    });
    

Gotchas and Tips

Pitfalls

  1. Stack Size:

    • Deep promise chains (e.g., >1000 then() calls) may cause stack overflows.
    • Fix: Use iterative resolution (built into Guzzle promises) or flatten chains.
  2. Unwrapping Foreign Promises:

    • Foreign promises (e.g., ReactPHP) lose wait()/cancel() support when forwarded.
    • Fix: Wrap foreign promises in Guzzle promises:
      $foreignPromise = new \React\Promise\Deferred()->promise();
      $guzzlePromise = new Promise(function () use ($foreignPromise) {
          return $foreignPromise;
      });
      
  3. Blocking wait():

    • wait() blocks execution until the promise resolves.
    • Fix: Avoid in production async code; use only for CLI/debugging.
  4. Cancellation Race Conditions:

    • Cancelling a promise may not immediately stop async operations.
    • Fix: Design async tasks to check cancellation flags periodically.
  5. Error Propagation:

    • Exceptions in then() callbacks are caught and forwarded as rejections.
    • Fix: Use try/catch in callbacks if you need to handle errors differently.

Debugging Tips

  • Check Promise State:
    $state = $promise->getState(); // 'pending', 'fulfilled', or 'rejected'
    
  • Inspect Rejection Reasons:
    $promise->then(null, function ($reason) {
        var_dump($reason); // Log or inspect the rejection reason
    });
    
  • Log Promise Chains: Use then() to log values/reasons at each step:
    $promise->then(function ($value) {
        logger()->info("Fulfilled with: " . $value);
    });
    

Extension Points

  1. Custom Promise Classes: Extend GuzzleHttp\Promise\Promise to add domain-specific logic:

    class ApiPromise extends Promise {
        public function __construct($endpoint) {
            parent::__construct(function () use ($endpoint) {
                return $this->fetch($endpoint);
            });
        }
    }
    
  2. Promise Utilities: Create helper functions for common patterns:

    function retryPromise($promise, $maxAttempts = 3) {
        return $promise->then(null, function ($reason) use ($promise, $maxAttempts) {
            if ($maxAttempts > 0) {
                return retryPromise($promise, $maxAttempts - 1);
            }
            throw $reason;
        });
    }
    
  3. Async/Await Sugar: Build a coroutine wrapper for cleaner syntax:

    function async(function $generator) {
        $coroutine = \GuzzleHttp\Promise\Coroutine::of($generator);
        return $coroutine->then(function ($result) {
            return $result;
        });
    }
    

Config Quirks

  • Task Queue: The global task queue (Utils::queue()) must be run manually in custom event loops.

  • PHP Version:

    • v1.x: Works with PHP 5.5–8.2 (legacy).
    • v2.x: Requires PHP 7.2.5+ (recommended for new projects).
  • Thread Safety: Promises are not thread-safe. Avoid sharing promises across threads.

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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata