Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Dynamic promise stack #46

Closed
bpolaszek opened this issue Nov 4, 2016 · 2 comments
Closed

Dynamic promise stack #46

bpolaszek opened this issue Nov 4, 2016 · 2 comments

Comments

@bpolaszek
Copy link
Contributor

bpolaszek commented Nov 4, 2016

Hello,

TL; DR

Guzzle's all($promises) function should be recursive: resolution of $promises may add new promises into the $promises stack. These new promises should not be left pending.

Example

I'm using Guzzle's all() function to resolve a collection of promises, stored in an iterator.
What if one of these promises, when resolved, adds a new promise to the stack?

Have a look at the following code:

$data       = new ArrayObject();
$promises   = new ArrayIterator();
$promises[] = $fooPromise = new \GuzzleHttp\Promise\Promise(function () use ($promises, &$fooPromise, $data) {
    var_dump('Loading foo');
    $data[] = 'foo';
    $fooPromise->resolve('foo');
});

$fooPromise->then(function () use (&$promises, $data) {

    # When $fooPromise is resolved, for some reason I may add some data with another promise
    $barPromise = new \GuzzleHttp\Promise\Promise(function () use ($promises, &$barPromise, $data) {
        var_dump('Loading bar');
        $data[] = 'bar';
        $barPromise->resolve('bar');
    });

    $promises[] = $barPromise;

});

$mainPromise = \GuzzleHttp\Promise\all($promises);
$mainPromise->wait();
var_dump($data->getArrayCopy());

I expect the following output:

string(11) "Loading foo"
string(11) "Loading bar"
array(2) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
}

But I get this:

string(11) "Loading foo"
array(1) {
  [0]=>
  string(3) "foo"
}

And my $secondPromise state is pending. Why is it not resolved?

Thank you,
Ben

@bpolaszek
Copy link
Contributor Author

up ?

@bpolaszek bpolaszek reopened this Nov 30, 2016
@bpolaszek
Copy link
Contributor Author

Hi everyone,

For people who ran into the same issue, here's a simple function to fix it:

use GuzzleHttp\Promise\PromiseInterface;

class PromiseStack {

    /**
     * @param PromiseInterface[]|array|\Traversable|\Generator $promises
     * @return PromiseInterface
     */
    public static function all($promises) : PromiseInterface {
        return \GuzzleHttp\Promise\all($promises)->then(function ($result) use (&$promises) {
            foreach ($promises AS $promise) {
                if (\GuzzleHttp\Promise\PromiseInterface::PENDING === $promise->getState()) {
                    return static::all($promises);
                }
            }
            return $result;
        });
    }

}

I just don't understand why this is not the default behavior of Guzzle's all() function...

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant