Giter Club home page Giter Club logo

Comments (9)

mtdowling avatar mtdowling commented on May 6, 2024

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.

mikegreiling avatar mikegreiling commented on May 6, 2024

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.

mtdowling avatar mtdowling commented on May 6, 2024

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.

Zxurian avatar Zxurian commented on May 6, 2024

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.

mtdowling avatar mtdowling commented on May 6, 2024

@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.

Zxurian avatar Zxurian commented on May 6, 2024

@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.

berarma avatar berarma commented on May 6, 2024

@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.

jaylinski avatar jaylinski commented on May 6, 2024

This may have been fixed with #135 in version 1.5.0.

from promises.

GrahamCampbell avatar GrahamCampbell commented on May 6, 2024

🎉

from promises.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.