mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
fix cancellation logic for server fn requests
This commit is contained in:
parent
60d883a26c
commit
e4f3cf9cca
2 changed files with 25 additions and 51 deletions
|
@ -39,18 +39,11 @@ pub mod browser {
|
|||
use super::Client;
|
||||
use crate::{
|
||||
error::ServerFnError,
|
||||
request::browser::{AbortOnDrop, BrowserRequest, RequestInner},
|
||||
request::browser::{BrowserRequest, RequestInner},
|
||||
response::browser::BrowserResponse,
|
||||
};
|
||||
use gloo_net::{http::Response, Error};
|
||||
use send_wrapper::SendWrapper;
|
||||
use std::{
|
||||
future::Future,
|
||||
marker::PhantomData,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use web_sys::AbortController;
|
||||
use std::future::Future;
|
||||
|
||||
/// Implements [`Client`] for a `fetch` request in the browser.
|
||||
pub struct BrowserClient;
|
||||
|
@ -64,54 +57,26 @@ pub mod browser {
|
|||
) -> impl Future<Output = Result<Self::Response, ServerFnError<CustErr>>>
|
||||
+ Send {
|
||||
SendWrapper::new(async move {
|
||||
let mut req = req.0.take();
|
||||
let req = req.0.take();
|
||||
let RequestInner {
|
||||
request,
|
||||
abort_ctrl,
|
||||
mut abort_ctrl,
|
||||
} = req;
|
||||
/*BrowserRequestFuture {
|
||||
request_fut: request.send(),
|
||||
abort_ctrl,
|
||||
cust_err: PhantomData,
|
||||
}*/
|
||||
request
|
||||
let res = request
|
||||
.send()
|
||||
.await
|
||||
.map(|res| BrowserResponse(SendWrapper::new(res)))
|
||||
.map_err(|e| ServerFnError::Request(e.to_string()))
|
||||
.map_err(|e| ServerFnError::Request(e.to_string()));
|
||||
|
||||
// at this point, the future has successfully resolved without being dropped, so we
|
||||
// can prevent the `AbortController` from firing
|
||||
if let Some(ctrl) = abort_ctrl.as_mut() {
|
||||
ctrl.prevent_cancellation();
|
||||
}
|
||||
res
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/*pin_project_lite::pin_project! {
|
||||
struct BrowserRequestFuture<Fut, CustErr>
|
||||
where
|
||||
Fut: Future<Output = Result<Response, Error>>,
|
||||
{
|
||||
#[pin]
|
||||
request_fut: Fut,
|
||||
abort_ctrl: Option<AbortOnDrop>,
|
||||
cust_err: PhantomData<CustErr>
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut, CustErr> Future for BrowserRequestFuture<Fut, CustErr>
|
||||
where
|
||||
Fut: Future<Output = Result<Response, Error>>,
|
||||
{
|
||||
type Output = Result<BrowserResponse, ServerFnError<CustErr>>;
|
||||
|
||||
fn poll(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Self::Output> {
|
||||
let this = self.project();
|
||||
match this.request_fut.poll(cx) {
|
||||
Poll::Ready(value) => todo!(),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
#[cfg(feature = "reqwest")]
|
||||
|
|
|
@ -25,11 +25,20 @@ pub(crate) struct RequestInner {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct AbortOnDrop(AbortController);
|
||||
pub(crate) struct AbortOnDrop(Option<AbortController>);
|
||||
|
||||
impl AbortOnDrop {
|
||||
/// Prevents the request from being aborted on drop.
|
||||
pub fn prevent_cancellation(&mut self) {
|
||||
self.0.take();
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AbortOnDrop {
|
||||
fn drop(&mut self) {
|
||||
self.0.abort();
|
||||
if let Some(inner) = self.0.take() {
|
||||
inner.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +81,7 @@ impl From<FormData> for BrowserFormData {
|
|||
fn abort_signal() -> (Option<AbortOnDrop>, Option<AbortSignal>) {
|
||||
let ctrl = AbortController::new().ok();
|
||||
let signal = ctrl.as_ref().map(|ctrl| ctrl.signal());
|
||||
(ctrl.map(AbortOnDrop), signal)
|
||||
(ctrl.map(|ctrl| AbortOnDrop(Some(ctrl))), signal)
|
||||
}
|
||||
|
||||
impl<CustErr> ClientReq<CustErr> for BrowserRequest {
|
||||
|
|
Loading…
Reference in a new issue