New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
calling a JS function in the spawn function -- possible? #128
Comments
#[bind(object)]
#[quickjs(bare)]
pub mod timer {
use rquickjs::{Ctx, Function};
use std::time::Duration;
use tokio::time;
#[quickjs(rename = "setInterval")]
pub async fn set_interval<'js>(func: Function<'js>, delay: Option<usize>) {
let duration = Duration::from_millis(delay.unwrap_or(0) as u64);
let mut interval = time::interval(duration);
loop {
interval.tick().await;
let _ = func.defer_call(());
}
}
#[quickjs(rename = "clearInterval")]
pub fn clear_interval(handle: usize) {}
#[quickjs(rename = "setTimeout")]
pub async fn set_timeout<'js>(func: Function<'js>, delay: Option<usize>) {
let duration = Duration::from_millis(delay.unwrap_or(0) as u64);
let mut interval = time::interval(duration);
interval.tick().await;
let _ = func.defer_call(());
}
#[quickjs(rename = "clearTimeout")]
pub fn clear_timeout(handle: usize) {} Well this doesn't work either... |
|
After looking to it somewhat more it seems that my previous comment is not entirely right. It might be safe but I am not entirely sure. We might be able to make rquickjs able to spawn futures which aren't |
I have managed to implement this way: #[bind(object)]
#[quickjs(bare)]
pub mod timer {
use rquickjs::{Context, Ctx, Function, Persistent};
use std::time::Duration;
use tokio::{select, time};
use tokio_util::sync::CancellationToken;
#[quickjs(cloneable)]
#[derive(Clone)]
pub struct CancellationTokenWrapper(CancellationToken);
#[quickjs(rename = "setInterval")]
pub fn set_interval(
func: Persistent<Function<'static>>,
delay: Option<usize>,
ctx: Ctx,
) -> CancellationTokenWrapper {
let delay = delay.unwrap_or(0) as u64;
let duration = Duration::from_millis(delay);
let mut interval = time::interval(duration);
let token = CancellationToken::new();
ctx.spawn({
let token = token.clone();
let context = Context::from_ctx(ctx).unwrap();
async move {
loop {
select! {
_ = token.cancelled() => break,
_ = interval.tick() => {
let _ = context.with(|ctx| func.clone().restore(ctx)?.defer_call(()));
}
}
}
}
});
CancellationTokenWrapper(token)
}
#[quickjs(rename = "clearInterval")]
pub fn clear_interval(token: CancellationTokenWrapper) {
token.0.cancel();
}
#[quickjs(rename = "setTimeout")]
pub fn set_timeout(
func: Persistent<Function<'static>>,
delay: Option<usize>,
ctx: Ctx,
) -> CancellationTokenWrapper {
let delay = delay.unwrap_or(0) as u64;
let duration = Duration::from_millis(delay);
let token = CancellationToken::new();
ctx.spawn({
let token = token.clone();
let context = Context::from_ctx(ctx).unwrap();
async move {
select! {
_ = token.cancelled() => { }
_ = time::sleep(duration) => {
let _ = context.with(|ctx| func.restore(ctx)?.defer_call(()));
}
}
}
});
CancellationTokenWrapper(token)
}
#[quickjs(rename = "clearTimeout")]
pub fn clear_timeout(token: CancellationTokenWrapper) {
token.0.cancel();
}
} If you think this is safe, let's close the issue for now. |
Yep that seems a way to do it safely. I'll close the issue. |
I want to implement setInterval/setTimeout so I wrote something like this:
However, it seems like it can't compile:
I have the
parallel
features on and maybe I can just ignore this for now, maybe I can workaround by using an async promise function and do the loop inside, but this would not be standard compliantThe text was updated successfully, but these errors were encountered: