luthfianto
luthfianto

Reputation: 1826

What's python's Task equivalent of a JS' promise.then().catch() without await?

This adds an success/error handler to the future like:

async function send(item) {
    // ...
}

for (const item of items) {
    const sendPromise = send(item);
    sendPromise
        .then(x => console.log(x))
        .catch(x => console.error(x))
}

instead of await-ing like:

for (const item of items) {
    const sendPromise = send(item);
    try {
        const x = await sendPromise
        console.log(x)
    } catch (e) {
        console.error(e)
    }
}

What's python's Task equivalent of a JS' promise.then() without await?

async def send(item):
    pass

for item of items:
    send_coro = send(item)
    send_task = asyncio.create_task(send_coro)
    # ?????
}

Upvotes: 1

Views: 1023

Answers (1)

user4815162342
user4815162342

Reputation: 155296

If I am reading the JavaScript correctly, it adds an error handler to the future. A literal translation would be something along the lines of:

def _log_err(fut):
    if fut.exception() is not None:
        print(f'error: {fut.exception()}')

for item in items:
    send_future = asyncio.create_task(send(item))
    send_future.add_done_callback(_log_err)

Note that the above is not idiomatic, as it resorts to callbacks and is less elegant than the original JavaScript, where then and catch return new futures which chain nicely.

A better approach is to use a helper coroutine to host the await. This doesn't require the outer function to be async def, thus being equivalent to the above:

async def _log_err(aw):
    try:
        return await aw
    except Exception as e:
        print(f'error: {e}')

for item in items:
    asyncio.create_task(_log_err(send(item)))

Upvotes: 4

Related Questions