MK Yung
MK Yung

Reputation: 4581

The equivalent of jquery $.when in Python Tornado

In jQuery $.when(promise1, promise2...) is used as a master promise to represent the overall status of its children promises. We can then attach .done(callback) to the $.when promise so that when ALL promise1, promise2... finish the callback will be executed.

In Python (Tornado), the Future acts similar to the promise in javascript, and the fetch() in AsyncHTTPClient returns a Future.

In the following code I have a list of futures

from tornado.httpclient import AsyncHTTPClient

httpclient = AsyncHTTPClient()
futures = [
    httpclient.fetch("http://google.com")
    httpclient.fetch("http://example.com")
    httpclient.fetch("http://example.org")
]

def all_futures_done_callback():
    ...

How do I execute the all_futures_done_callback when all futures finished?

Upvotes: 2

Views: 330

Answers (2)

Ben Darnell
Ben Darnell

Reputation: 22134

In a coroutine it's easy to wait for multiple futures; just yield them all as a list:

@gen.coroutine
def f():
    futures = [
        httpclient.fetch("http://google.com")
        httpclient.fetch("http://example.com")
        httpclient.fetch("http://example.org")
    ]
    responses = yield futures

To do this with callbacks instead of coroutines you'll need something like mgilson's answer.

Upvotes: 2

mgilson
mgilson

Reputation: 309899

It seems to me that you'll need to build this functionality yourself. This is untested, but something like this seems like it should work:

class FutureCollection(Future):
    def __init__(self, *args, **kwargs):
        super(FutureCollection, self).__init__(*args, **kwargs)
        self._waiting_for = []

    def _check_all_done_and_resolve(self, future):
        if all(f.done() for f in self._waiting_for):
            # Maybe check for exceptions a. la.
            # http://tornado.readthedocs.org/en/latest/_modules/tornado/concurrent.html#chain_future
            self.set_result(None)  # Not sure what the result should be.

    def add_future(self, future):
        self._waiting_for.append(future)
        future.add_done_callback(self._check_all_done_and_resolve)

    @property
    def futures(self):
        # Read-only access to the futures that have been added.
        return iter(self._waiting_for)

Upvotes: 1

Related Questions