Comments (9)
This is not a bug. You need to either call wait() on a promise or manually tick the queue.
A queue is used to invoke callbacks to prevent recursion and to guarantee a predictable order for callbacks -- for example, if we invoked callbacks immediately when a promise is fulfilled without queueing them, then we could invoke callbacks out of the order in which they were added to the promise (e.g., callbacks are added on a pending promise, pending promise is fulfilled, callbacks are added, then the queue is ticked to invoke callbacks).
What part of the documentation is wrong?
from promises.
I guess I misunderstood the use of the word "immediately" in the following comment blocks and documentation sections. Perhaps different wording would be appropriate.
https://github.com/guzzle/promises/blob/master/src/FulfilledPromise.php#L7
https://github.com/guzzle/promises/blob/master/src/RejectedPromise.php#L7
https://github.com/guzzle/promises/blob/master/src/Promise.php#L42
https://github.com/guzzle/promises/blob/master/README.md#fulfilledpromise
from promises.
Yeah, the wording there is a bit ambiguous as to what "immediately" means. The intent is that there is no fulfillment required for the promise to resolve the callbacks. Maybe it should be changed to "immediately on the next tick"
from promises.
so this was actually referenced in a problem I'm trying to solve with https://github.com/aws/aws-sdk-php .
I'm trying to write a routine such that there is a main loop (Loop-A) that runs over a fixed list checking for certain triggers. If a trigger is found, it initiates an asynchronous upload that returns a Guzzle Promise, which I attach a ->then()
to. This issue came up because the callbacks I'm attaching via then()
aren't firing upon completion of the upload because of the above problem of not resolving until the next "tick' of the event loop.
Is there anything I can run as part of the main loop (loop-a) that will check through all existing promises to see if any are fulfilled and then resolve them? Or possibly a better solution, a way of having the promises being fulfilled without needing an additional tick of the queue of the callbacks are registered to the specific promises?
from promises.
@Zxurian can you provide a reproducible code example I can see? My first thoughts are that you need to chain your promises if you want your callbacks to be invoked without an extra tick. You can get access to the TaskQueue and invoke run()
in your loop as well. See https://github.com/guzzle/promises/blob/master/src/TaskQueue.php
from promises.
@mtdowling using the following code example with https://github.com/aws/aws-sdk-php
<?php
$uploading = 0;
$AWS = new Aws\Sdk([
'version' => 'latest',
'region' => 'us-east-1',
'credentials' => [
'key' => '***',
'secret' => '***',
]
]);
$S3 = $AWS->createS3();
echo "beginning first promise\n";
$uploading ++;
$promise1 = $S3->uploadAsync('tantor-books', 'Test/test.xml', fopen('/mnt/olympus/Books/0087_CoalHuman/Download/0087_CoalHuman.xml', 'r'));
$promise1->then(function() use ($uploading) {
$uploading --;
});
echo "beginning second promise\n";
$uploading ++;
$promise2 = $S3->uploadAsync('tantor-books', 'Test/test.zip', fopen('/mnt/olympus/Books/0087_CoalHuman/Download/0087_CoalHuman.zip', 'r'));
$promise2->then(function() use ($uploading) {
$uploading --;
});
echo "beginning loop\n";
while ($uploading != 0) {
echo 'uploading: '.$uploading."\n";
}
TL;DR - The script will never exit as the then()
functions never get called.
I'm also having a discussion at https://gitter.im/aws/aws-sdk-php about it and @jeskew says this is by design. and that I'll need to manually tick the queue forward before the uploads will actually start. What I'd like is to start files uploading while the main loop is still going, then wait()
on anything that's still transferring at the end before proceeding, and it's sounding like in order to do that, I need to manually tick the Guzzle queue after each call to uploadAsync()
in order to start it.
from promises.
@Zxurian, I found this issue while working on a similar problem. PHP isn't multi-threaded so while your loop is running nothing else will run. That includes your S3 client code, responsible of fulfilling the promises, and the promise queue. Async operations are simulated by waiting on external events and queueing tasks.
You could add this to your loop:
GuzzleHttp\Promise\queue->run();
But it won't have anything to run because the client code didn't have a chance to fulfill the promises. You should be ticking your S3 client code instead (in case that's possible) or wait on it. When you call the tick or wait operations on the client it simulates multi-threading by chaining all the operations. So you should do this instead of creating your own wait loop, or you should be able to reproduce the same behavior inside your loop.
I guess it should be done like this:
<?php
$uploading = 0;
$AWS = new Aws\Sdk([
'version' => 'latest',
'region' => 'us-east-1',
'credentials' => [
'key' => '***',
'secret' => '***',
]
]);
$S3 = $AWS->createS3();
echo "beginning first promise\n";
$uploading ++;
$promise1 = $S3->uploadAsync('tantor-books', 'Test/test.xml', fopen('/mnt/olympus/Books/0087_CoalHuman/Download/0087_CoalHuman.xml', 'r'));
$promise1->then(function() use ($uploading) {
$uploading --;
echo 'uploading: '.$uploading."\n";
});
echo "beginning second promise\n";
$uploading ++;
$promise2 = $S3->uploadAsync('tantor-books', 'Test/test.zip', fopen('/mnt/olympus/Books/0087_CoalHuman/Download/0087_CoalHuman.zip', 'r'));
$promise2->then(function() use ($uploading) {
$uploading --;
echo 'uploading: '.$uploading."\n";
});
echo "beginning loop\n";
// Call here your S3 wait function or unwrap the promises that in turn will do the same.
GuzzleHttp\Promise\unwrap([$promise1, $promise2]);
Please, correct me if I'm wrong.
from promises.
This may have been fixed with #135 in version 1.5.0.
from promises.
🎉
from promises.
Related Issues (20)
- issue with php 7.3+ HOT 2
- State inconsistency with chained promises
- 1.4.0 Release HOT 4
- exception throwing HOT 4
- 'each' has deprecated since php 7.2 HOT 2
- PHP 8 : TypeError: method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given HOT 3
- undefined method named "of" of class "GuzzleHttp\Promise\Coroutine" HOT 4
- each_limit skipping promises and failing with "Invoking the wait callback did not resolve the promise" HOT 9
- StreamHandler and HTTP/2 does not seem to work HOT 2
- Persist order of keys for Utils::settle HOT 1
- Cannot Bootstrap promise v.1.4.0
- Memory leak when using \GuzzleHttp\Pool with empty array of requests HOT 4
- EachPromise not running last item's callback HOT 3
- Add $config to the signatures of Utils::all and Each::of ?
- Grammatical errors HOT 1
- Allow all promise collection wrappers to dynamically add promises via $recursive option
- undefined function GuzzleHttp\Promise\all() HOT 1
- The each() function is deprecated HOT 2
- Coroutines : Exceptions thrown before the 1st yield are rethrown instead of rejecting the promise
- False positive warnings for each function
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from promises.