Skip to content
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

Stream from AsyncIterator in wasm-bindgen-futures #2399

Open
olanod opened this issue Dec 19, 2020 · 3 comments
Open

Stream from AsyncIterator in wasm-bindgen-futures #2399

olanod opened this issue Dec 19, 2020 · 3 comments

Comments

@olanod
Copy link
Contributor

olanod commented Dec 19, 2020

AsyncIterator in JS is the native equivalent of Promise to represent multiple future values instead of one just as in Rust we have Future and Stream(soon in the standard library). Instead of creating a separate utility crate that converts async iterators to Rust streams I propose having that in function(e.g. iter_to_stream) in the wasm-bindgen-futures crate since the feature(can be behind a flag) is very "futures" related.

@mattgibb
Copy link

mattgibb commented Dec 29, 2020

This would be awesome! Would it be possible to have the opposite too i.e. subscribe to a Rust Stream from Javascript via the registration of a callback/RxJS Observable or similar? Apologies in advance if this has an obvious solution, I am at the beginning of my journey with Rust...

I know already that you can call pre-existing global/static JS functions from Rust via an extern "C" block. However, it would be great to be able to manage subscriptions dynamically. I tried passing in a &js_sys::Function callback, but I couldn't get the callback to survive longer than the registration function:

use std::collections::HashMap;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
#[derive(Default)]
pub struct Subscribable<'a> { // compiler error that lifetimes aren't available 
  xs: Vec<u32>,
  subscribers: HashMap<u32, &'a js_sys::Function>,
  next_id: u32,
}

#[wasm_bindgen]
impl Subscribable {
  pub fn new() -> Self {
    Self {
      xs: vec![1, 2, 3],
      subscribers: HashMap::new(),
      next_id: 0,
    }
  }

  pub fn each(&self, callback: &js_sys::Function) {
    let this = JsValue::null();

    for &x in &self.xs {
      let x = JsValue::from(x);
      callback.call1(&this, &x);
    }
  }

  // subscriber can't survive past the end of this method
  pub fn subscribe(&mut self, subscriber: &js_sys::Function) -> u32 {
    let id = self.next_id;
    self.subscribers.insert(id, subscriber);
    self.next_id += 1;
    id
  }

  pub fn unsubscribe(&self, subscription: u32) {
    self.subscribers.remove(&subscription);
  }
}

Any pointers would be hugely appreciated!

@sisou
Copy link

sisou commented Feb 16, 2023

@mattgibb Hi! Did you ever figure out how to do this? I'm at the same point now, having streams in Rust that I want to react to in JS, without a separate global listener function import. Either with callbacks like your code above, or by converting to an AsyncIterator.

@kitty-eu-org
Copy link

@mattgibb你好!你有想过如何做到这一点吗?我现在处于同一点,在 Rust 中有流,我想在 JS 中做出反应,而不需要单独的全局侦听器函数导入。使用像上面的代码这样的回调,或者转换为 AsyncIterator。

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants