gradio-app / gradio

Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!
http://www.gradio.app
Apache License 2.0
33.96k stars 2.58k forks source link

Canceling event with JavaScript handler doesn't work #7750

Closed deep-diver closed 4 weeks ago

deep-diver commented 8 months ago

Describe the bug

when events are chained, and there is an event with JavaScript handler in between, the chain of events can not be canceled. I verified this issue does not happen when I detached that event.

Have you searched existing issues? 🔎

Reproduction

When I remove the second event handler (on the then method), it works perfect. However, I get error whenever I try to cancel an event with JavaScript handler.

import asyncio
import gradio as gr

async def test():
    yield "a"
    await asyncio.sleep(1)
    yield "b"
    await asyncio.sleep(1)
    yield "c"
    await asyncio.sleep(1)
    yield "d"

with gr.Blocks() as demo:
    txt = gr.Textbox("showing results")
    action_btn = gr.Button("action")
    cancel_btn = gr.Button("cancel")
    action_event = action_btn.click(
        test,
        None, txt
    ).then(
        None, None, None,
        js=""
    )
    cancel_btn.click(None, None, None, cancels=[action_event])

demo.queue().launch()

Screenshot

No response

Logs

ValueError: Queue needs to be enabled! You may get this error by either 1) passing a function that uses the yield keyword into an interface without enabling the queue or 2) defining an event that cancels another event without enabling the queue. Both can be solved by calling .queue() before .launch()

### System Info

```shell
Google Colab and Hugging Face Space

Severity

Blocking usage of gradio

freddyaboulton commented 7 months ago

So js events are not cancelable. You can still use then but you just have to split it up so you pass the click event to cancels. Right now you're passing the js event (the last event in the chain).

import asyncio
import gradio as gr

async def test():
    yield "a"
    await asyncio.sleep(1)
    yield "b"
    await asyncio.sleep(1)
    yield "c"
    await asyncio.sleep(1)
    yield "d"

with gr.Blocks() as demo:
    txt = gr.Textbox("showing results")
    action_btn = gr.Button("action")
    cancel_btn = gr.Button("cancel")
    click = action_btn.click(
        test,
        None, txt
    )
    click.then(
        None, None, None,
        js=""
    )
    cancel_btn.click(None, None, None, cancels=[click])

demo.queue().launch()
abidlabs commented 4 weeks ago

Closing as this seems to be addressed