⚡ 使用 #[neon::export] 异步

最简单的异步方式:

rust
#[neon::export]
async fn fetch_data(url: String) -> Result {
    let response = reqwest::get(&url).await?;
    let body = response.text().await?;
    Ok(body)
}

JavaScript 端自动获得 Promise:

javascript
const { fetchData } = require('./native');

async function main() {
    const data = await fetchData('https://api.example.com/data');
    console.log(data);
}

🔄 使用 Task

更灵活的异步任务:

rust
use neon::prelude::*;

struct ComputeTask {
    input: i32,
}

impl Task for ComputeTask {
    type Output = i32;
    type Error = String;
    type JsEvent = JsNumber;

    fn perform(&self) -> Result {
        // 在后台线程执行
        Ok(self.input * 2)
    }

    fn complete(self, mut cx: TaskContext, result: Result) -> JsResult {
        match result {
            Ok(val) => Ok(cx.number(val as f64)),
            Err(e) => cx.throw_error(e),
        }
    }
}

fn compute_async(mut cx: FunctionContext) -> JsResult {
    let input = cx.argument::(0)?.value(&mut cx) as i32;
    let task = ComputeTask { input };
    
    let promise = task.schedule(&mut cx)?;
    Ok(promise)
}

📋 Promise 创建

rust
use neon::prelude::*;

fn create_promise(mut cx: FunctionContext) -> JsResult {
    let (deferred, promise) = cx.promise();
    
    // 可以在其他线程 resolve
    let channel = cx.channel();
    thread::spawn(move || {
        let result = expensive_computation();
        
        channel.send(move |mut cx| {
            let value = cx.string(result);
            deferred.resolve(&mut cx, value);
            Ok(())
        });
    });
    
    Ok(promise)
}

⚠️ 注意事项

  • 异步函数不会阻塞 JavaScript 主线程
  • 长时间任务使用 Task 或 #[neon::export] async
  • 跨线程通信使用 Channel
  • 避免在异步中访问 JavaScript 对象