Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Promise not working as async without wait() #89

Open
zelin opened this issue Mar 16, 2018 · 3 comments
Open

Promise not working as async without wait() #89

zelin opened this issue Mar 16, 2018 · 3 comments

Comments

@zelin
Copy link

zelin commented Mar 16, 2018

The code works if i do $promise->wait();, however i am not sure how can i call the promise to work async.

foreach ($entries as $key=>$value)
        {     
                $promise = new Promise(function() use (&$promise, $key, $value) 
                {   
                    // Do some heavy lifting work.
                    $mainOutput = array($key, $output, $value);
                    $promise->resolve($mainOutput);
                });

                $promise->then(
                    // $onFulfilled
                    function ($mainOutput)
                    {
                        static::addToResponse($mainOutput);
                    },
                    // $onRejected
                    function ($reason) 
                    {
                        echo 'The promise was rejected.';
                    }
                );
            if(static::$sync)  
            {    
                $promise->wait();
            }
            else
            {

            }
        }
@dignat
Copy link

dignat commented Jul 12, 2018

I am having the same issue. Any solutions, yet?

@mcglonelevi
Copy link

From what I can tell, you are trying to call multiple promises at once and wait for them to return? If this is the case, there is an all function here:

https://github.com/guzzle/promises/blob/master/src/functions.php

/**
 * Given an array of promises, return a promise that is fulfilled when all the
 * items in the array are fulfilled.
 *
 * The promise's fulfillment value is an array with fulfillment values at
 * respective positions to the original array. If any promise in the array
 * rejects, the returned promise is rejected with the rejection reason.
 *
 * @param mixed $promises Promises or values.
 * @param bool $recursive - If true, resolves new promises that might have been added to the stack during its own resolution.
 *
 * @return PromiseInterface
 */

@TheTechsTech
Copy link

I been working on just this problem intermixed with #44 (comment) and reactphp/promise#66.

According to promises-aplus/constructor-spec#18 the constructor implemented here is invalid. ReactPHP is valid to those spec's, but it will fail at runtime on your code example, and most Guzzle promise tests that tries to access an promise reference object of itself, it will produce an runtime error, access member method on null.

In order for your promise to work async, something like the following needs to be added to the constructor:

$promiseFunction = function () use($waitFn) {
	if (is_callable($waitFn)) {
		$waitFn([$this, 'resolve'], [$this, 'reject']);
	}
};

try {
	$promiseFunction();
} catch (\Throwable $e) {
	queue()->add($promiseFunction);
} catch (\Exception $exception) {
	queue()->add($promiseFunction);
}

This will end up producing an valid constructor according to spec's. It basically traps the otherwise error, and adds the callback to the event queue. However, it solves and introduces a few problems and wait method will need refactoring.

My guzzle/promises fork https://github.com/techno-express/promises/tree/interoperable, shows the problems solved and new errors created. The errors revealed should have not been produced, I applied similar to ReactPHP.

In my reactphp/promise fork https://github.com/techno-express/promise/tree/interoperable, I 've added an wait method to the library and it will pass most Guzzle wait implemented promise tests afterwards. It's simple as adding run() to the call, then check results.

For more background, the process I took started on another promise library in Sabre.io sabre-io/event#66, which is similar to ReactPHP implementations, but had an wait method not constructed like Guzzle here. Since ReactPHP have no real promise tests or examples, reactphp/promise#103, reactphp/promise#127, reactphp/promise#91, just a lot of mock tests. I used Sabre.io, and Guzzle promise tests, the ones it should pass, and ReactPHP fails some tests it shouldn't. There implementations should pass similar coded examples, if following JavaScript promise spec's.

I will submit PR, only if requested.

The other main change I made was to easily use any event loop implementation as reactphp/promise#64. The wait method here is an forethought of the whole library to function, not an afterthought feature, that i find, can't be easily rewrote/refactored.

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

No branches or pull requests

4 participants