diff --git a/.changeset/forty-pans-add.md b/.changeset/forty-pans-add.md new file mode 100644 index 0000000000..faed0a4cd1 --- /dev/null +++ b/.changeset/forty-pans-add.md @@ -0,0 +1,6 @@ +--- +"@gradio/client": patch +"gradio": patch +--- + +fix:Fix UI freeze on rapid generators diff --git a/client/js/src/client.ts b/client/js/src/client.ts index 5abc440d5d..6355d5a04c 100644 --- a/client/js/src/client.ts +++ b/client/js/src/client.ts @@ -290,6 +290,7 @@ export function api_factory( let pending_stream_messages: Record = {}; // Event messages may be received by the SSE stream before the initial data POST request is complete. To resolve this race condition, we store the messages in a dictionary and process them when the POST request is complete. let event_stream: EventSource | null = null; const event_callbacks: Record Promise> = {}; + const unclosed_events: Set = new Set(); let config: Config; let api_map: Record = {}; @@ -902,9 +903,6 @@ export function api_factory( ) { if (event_callbacks[event_id]) { delete event_callbacks[event_id]; - if (Object.keys(event_callbacks).length === 0) { - close_stream(); - } } } } catch (e) { @@ -928,6 +926,7 @@ export function api_factory( delete pending_stream_messages[event_id]; } event_callbacks[event_id] = callback; + unclosed_events.add(event_id); if (!stream_open) { open_stream(); } @@ -1042,7 +1041,14 @@ export function api_factory( ) ); } else if (event_callbacks[event_id]) { - await event_callbacks[event_id](_data); + if (_data.msg === "process_completed") { + unclosed_events.delete(event_id); + if (unclosed_events.size === 0) { + close_stream(); + } + } + let fn = event_callbacks[event_id]; + window.setTimeout(fn, 0, _data); // need to do this to put the event on the end of the event loop, so the browser can refresh between callbacks and not freeze in case of quick generations. See https://github.com/gradio-app/gradio/pull/7055 } else { if (!pending_stream_messages[event_id]) { pending_stream_messages[event_id] = [];