Rust WebAssembly计时器库zduny-wasm-timer的使用,实现高性能跨平台时间管理与延迟任务

Rust WebAssembly计时器库zduny-wasm-timer的使用,实现高性能跨平台时间管理与延迟任务

zduny-wasm-timer是一个Rust库,它导出了InstantDelayIntervalTimeout结构体。

在非WASM目标上,它会重新导出tokio-timer中的类型。在WASM目标上,它使用web-sysjs-sys来实现这些功能。

该库支持在Web Workers中使用。

安装

在项目目录中运行以下Cargo命令:

cargo add zduny-wasm-timer

或者在Cargo.toml中添加以下行:

zduny-wasm-timer = "0.2.9"

完整示例代码

以下是一个使用zduny-wasm-timer实现计时器和延迟任务的完整示例:

use zduny_wasm_timer::{Delay, Instant, Interval, Timeout};
use std::time::Duration;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn run_timer_examples() {
    // 示例1:使用Instant测量时间间隔
    let start = Instant::now();
    // 执行一些操作...
    let elapsed = start.elapsed();
    log::info!("操作耗时: {:?}", elapsed);

    // 示例2:使用Delay实现延迟任务
    Delay::new(Duration::from_secs(2)).await;
    log::info!("2秒延迟后执行的任务");

    // 示例3:使用Interval实现定时任务
    let mut interval = Interval::new(Duration::from_secs(1));
    for _ in 0..5 {
        interval.next().await;
        log::info!("每秒触发一次的定时任务");
    }

    // 示例4:使用Timeout设置超时
    let timeout = Timeout::new(Duration::from_secs(3), async {
        log::info!("超时前完成的任务");
    });
    
    if let Err(_) = timeout.await {
        log::info!("任务超时");
    }
}

使用说明

  1. Instant - 用于测量时间间隔的高精度时间点
  2. Delay - 用于实现延迟任务的未来(Future)
  3. Interval - 用于创建周期性定时器的迭代器
  4. Timeout - 用于设置任务超时

相关技术

  • wasm-bindgen
  • web-sys
  • js-sys

该库采用MIT许可证,适用于需要跨平台时间管理和延迟任务处理的WebAssembly应用场景。


扩展完整示例demo

以下是一个更完整的WASM计时器应用示例,展示了如何在浏览器环境中使用zduny-wasm-timer:

use zduny_wasm_timer::{Delay, Instant, Interval, Timeout};
use std::time::Duration;
use wasm_bindgen::prelude::*;
use web_sys::console;

// 初始化日志
#[wasm_bindgen(start)]
pub fn start() {
    console_error_panic_hook::set_once();
    console::log_1(&"WASM计时器应用已启动".into());
}

// 计时器功能封装
#[wasm_bindgen]
pub struct TimerApp {
    interval: Option<Interval>,
    timeout: Option<Timeout>,
}

#[wasm_bindgen]
impl TimerApp {
    // 创建新计时器应用
    pub fn new() -> Self {
        Self {
            interval: None,
            timeout: None,
        }
    }

    // 测量函数执行时间
    pub fn measure(&self, callback: &js_sys::Function) {
        let start = Instant::now();
        
        // 调用JS回调函数
        let _ = callback.call0(&JsValue::NULL);
        
        let duration = start.elapsed();
        console::log_1(&format!("函数执行耗时: {:?}", duration).into());
    }

    // 启动延迟任务
    pub async fn start_delay(&self, seconds: u64) {
        Delay::new(Duration::from_secs(seconds)).await;
        console::log_1(&format!("{}秒延迟任务完成", seconds).into());
    }

    // 启动定时器
    pub fn start_interval(&mut self, seconds: u64, callback: js_sys::Function) {
        let mut interval = Interval::new(Duration::from_secs(seconds));
        
        wasm_bindgen_futures::spawn_local(async move {
            loop {
                interval.next().await;
                let _ = callback.call0(&JsValue::NULL);
            }
        });
        
        self.interval = Some(interval);
    }

    // 设置超时任务
    pub fn set_timeout(&mut self, seconds: u64, callback: js_sys::Function) {
        let timeout = Timeout::new(Duration::from_secs(seconds), async {
            let _ = callback.call0(&JsValue::NULL);
        });
        
        wasm_bindgen_futures::spawn_local(async move {
            if let Err(_) = timeout.await {
                console::log_1(&"任务超时".into());
            }
        });
        
        self.timeout = Some(timeout);
    }
}

这个扩展示例展示了:

  1. 如何封装计时器功能到WASM可调用的结构中
  2. 如何与JavaScript交互(通过回调函数)
  3. 更完整的异步任务处理
  4. 错误处理和日志记录

使用时需要在JavaScript中这样调用:

// 初始化WASM模块
import init, { TimerApp } from './pkg/your_wasm_module.js';

async function run() {
    await init();
    const timer = TimerApp.new();
    
    // 测量性能
    timer.measure(() => {
        // 要测量的代码
    });
    
    // 延迟任务
    timer.start_delay(3);
    
    // 定时器
    timer.start_interval(1, () => {
        console.log("定时器触发");
    });
    
    // 超时任务
    timer.set_timeout(5, () => {
        console.log("任务完成");
    });
}

run();

1 回复

zduny-wasm-timer:Rust WebAssembly计时器库的使用指南

简介

zduny-wasm-timer是一个专为Rust和WebAssembly设计的计时器库,提供了高性能的跨平台时间管理和延迟任务执行功能。它特别适合需要在WebAssembly环境中处理时间相关操作的场景。

主要特性

  • 跨平台支持(包括Web和原生环境)
  • 高性能的时间管理
  • 延迟任务执行
  • 定时器功能
  • 与Web API无缝集成

安装

在Cargo.toml中添加依赖:

[dependencies]
zduny-wasm-timer = "0.2"

基本用法

延迟执行

use zduny_wasm_timer::{Delay, Instant};

async fn delayed_task() {
    let start = Instant::now();
    Delay::new(std::time::Duration::from_secs(1)).await;
    println!("执行延迟1秒后的任务,实际延迟时间: {:?}", start.elapsed());
}

定时器

use zduny_wasm_timer::{Interval, Instant};

async fn periodic_task() {
    let mut interval = Interval::new(std::time::Duration::from_secs(1));
    let start = Instant::now();
    
    for _ in 0..5 {
        interval.next().await;
        println!("定时任务执行,距离开始时间: {:?}", start.elapsed());
    }
}

时间测量

use zduny_wasm_timer::Instant;

fn measure_time() {
    let start = Instant::now();
    
    // 执行一些操作...
    std::thread::sleep(std::time::Duration::from_millis(500));
    
    let elapsed = start.elapsed();
    println!("操作耗时: {:?}", elapsed);
}

在WebAssembly中使用

use wasm_bindgen::prelude::*;
use zduny_wasm_timer::{Delay, Instant};

#[wasm_bindgen]
pub async fn start_timer(seconds: u32) {
    let start = Instant::now();
    Delay::new(std::time::Duration::from_secs(seconds.into())).await;
    let elapsed = start.elapsed();
    
    web_sys::console::log_1(&format!("定时器触发,延迟了 {:?}", elapsed).into());
}

高级用法

取消延迟任务

use zduny_wasm_timer::{Delay, Instant};

async fn cancellable_delay() {
    let delay = Delay::new(std::time::Duration::from_secs(5));
    
    // 在另一个任务中取消延迟
    let handle = delay.handle();
    std::thread::spawn(move || {
        std::thread::sleep(std::time::Duration::from_secs(2));
        handle.cancel();
    });
    
    match delay.await {
        Ok(()) => println!("延迟完成"),
        Err(_) => println!("延迟被取消"),
    }
}

精确时间间隔

use zduny_wasm_timer::{Interval, Instant};

async fn precise_interval() {
    let mut interval = Interval::new_at(
        Instant::now() + std::time::Duration::from_secs(1),
        std::time::Duration::from_secs(1)
    );
    
    for _ in 0..5 {
        interval.next().await;
        println!("精确时间间隔任务执行");
    }
}

完整示例Demo

下面是一个完整的WebAssembly应用示例,展示了如何使用zduny-wasm-timer库:

use wasm_bindgen::prelude::*;
use zduny_wasm_timer::{Delay, Instant, Interval};

// 延迟执行示例
#[wasm_bindgen]
pub async fn demo_delay(seconds: u32) {
    let start = Instant::now();
    Delay::new(std::time::Duration::from_secs(seconds.into())).await;
    let elapsed = start.elapsed();
    
    web_sys::console::log_1(&format!("延迟任务完成,延迟了 {:?}", elapsed).into());
}

// 定时器示例
#[wasm_bindgen]
pub async fn demo_interval(count: u32) {
    let mut interval = Interval::new(std::time::Duration::from_secs(1));
    let start = Instant::now();
    
    for i in 0..count {
        interval.next().await;
        web_sys::console::log_1(
            &format!("定时器触发 #{}, 距离开始: {:?}", i+1, start.elapsed()).into()
        );
    }
}

// 取消延迟任务示例
#[wasm_bindgen]
pub async fn demo_cancellable() {
    let delay = Delay::new(std::time::Duration::from_secs(5));
    let handle = delay.handle();
    
    // 在wasm中可以使用setTimeout模拟取消操作
    let closure = Closure::once(move || handle.cancel());
    web_sys::window()
        .unwrap()
        .set_timeout_with_callback_and_timeout_and_arguments_0(
            closure.as_ref().unchecked_ref(),
            2000
        )
        .unwrap();
    
    match delay.await {
        Ok(()) => web_sys::console::log_1(&"延迟完成".into()),
        Err(_) => web_sys::console::log_1(&"延迟被取消".into()),
    }
}

注意事项

  1. 在WebAssembly环境中使用时,确保你的项目配置了正确的target(如wasm32-unknown-unknown
  2. 对于长时间运行的任务,考虑使用set_timeoutset_interval的Web API替代方案
  3. 在原生环境和WebAssembly环境中,时间精度可能有所不同

性能建议

  1. 避免创建大量短时间间隔的定时器
  2. 对于高频时间测量,考虑使用Instant::now()而不是系统时间
  3. 重用Interval实例而不是创建新的实例

这个库为Rust和WebAssembly提供了可靠的时间管理解决方案,特别适合需要跨平台时间操作和延迟任务执行的场景。

回到顶部