|
1 | 1 | mod handler; |
2 | 2 |
|
3 | | -use futures::StreamExt; |
4 | | -use node_bridge::{bindings::AbortSignal, prelude::*}; |
| 3 | +use std::future::IntoFuture; |
| 4 | + |
| 5 | +use futures::{ |
| 6 | + future::{select, Either}, |
| 7 | + StreamExt, |
| 8 | +}; |
| 9 | +use node_bridge::{bindings::AbortSignal, futures::Defer, prelude::*}; |
5 | 10 | use serde_json::json; |
6 | 11 | use wasm_bindgen::prelude::*; |
7 | 12 | use wasm_bindgen_futures::future_to_promise; |
@@ -49,7 +54,17 @@ pub async fn generate_project(prompt: &str, handler: ProjectHandler) -> Result<J |
49 | 54 | cancellable: true, |
50 | 55 | }, |
51 | 56 | closure_once!(|progress: Progress, abort_signal: AbortSignal| { |
52 | | - future_to_promise(async move { |
| 57 | + let defer_abort = Defer::new(); |
| 58 | + let defer_abort_clone = defer_abort.clone(); |
| 59 | + abort_signal.add_event_listener( |
| 60 | + "abort", |
| 61 | + closure_once!(|| { |
| 62 | + defer_abort_clone.resolve(JsValue::null()); |
| 63 | + }) |
| 64 | + .into_js_value(), |
| 65 | + ); |
| 66 | + |
| 67 | + let task = async move { |
53 | 68 | let mut state: StreamResponseState = |
54 | 69 | make_stream_request("/gen_project", &json!({ "description": prompt })) |
55 | 70 | .send() |
@@ -107,6 +122,14 @@ pub async fn generate_project(prompt: &str, handler: ProjectHandler) -> Result<J |
107 | 122 | } |
108 | 123 | drop(data_stream); |
109 | 124 | state.complete().await.map(|_| JsValue::null()) |
| 125 | + }; |
| 126 | + |
| 127 | + future_to_promise(async move { |
| 128 | + let task = std::pin::pin!(task); |
| 129 | + match select(defer_abort.into_future(), task).await { |
| 130 | + Either::Left((_, _)) => Ok(JsValue::null()), |
| 131 | + Either::Right((result, _)) => result, |
| 132 | + } |
110 | 133 | }) |
111 | 134 | }) |
112 | 135 | .into_js_value() |
|
0 commit comments