-
Notifications
You must be signed in to change notification settings - Fork 119
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
xilem_web: Add MemoizedStream view #757
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a few comments, no real blockers though, thanks!
(Ideally we would also have an example showing a use-case for this, but I don't want to block on that...)
Co-authored-by: Philipp Mildenberger <philipp@mildenberger.me>
Co-authored-by: Philipp Mildenberger <philipp@mildenberger.me>
Co-authored-by: Philipp Mildenberger <philipp@mildenberger.me>
Of course, that will come. |
log::debug!("Run app logic"); | ||
|
||
let search_stream = memoized_stream( | ||
(state.search_term.clone(), state.db.clone()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit messy, because the first argument (state.search_term
) is what should be monitored,
the second (state.db
) is only there to make it available for stream generation (in create_search_stream
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Philipp-M
I have now changed the implementation so that the app state is injected again before the future is initialized.
This has two advantages:
- Only the data that is to be monitored for changes needs to implement
PartialEq
andClone
- The point in time at which the future is created is now easier to grasp.
The API now looks like this:
memoized_await(
50, // data to watch
|state, watched_data| {
state.async_call_started = true; // before it was debounced
my_aync_call(state.non_watched_data, watched_data)
},
|state, result| { / * ... */ }
)
The implementation might be not the best, but at least in my manual tests it worked 😉
4aed1f3
to
261aa42
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the example!
I hope it's not too much to ask for and I think we can also use this and iterate in later PRs.
Though I would've thought of something that's more of a real-world use-case (and possibly use html instead of console log, as this more obviously shows what the example is about).
Maybe with inspiration from something like this, with e.g. something like this: https://docs.rs/wasm-streams/latest/wasm_streams/readable/struct.ReadableStream.html#method.into_stream
F: Future<Output = FOut> + 'static, | ||
InitFuture: Fn(&Data) -> F + 'static, | ||
InitFuture: Fn(&mut State, &Data) -> F + 'static, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've thought about adding this, but have hoped that the memoized data is enough (as this does make this even more imperative).
This is relevant. I.e. we should find a good (intuitive but non-magic/foot-gunny) way to handle this imperative stuff more generally.
That said I think we can add that, I've done similar in #452 (though possibly a reason why I haven't merged that yet).
schedule_update_fn: None, | ||
schedule_update_timeout_handle: None, | ||
update: false, | ||
thunk: Rc::new(thunk), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I think this probably is fine, but I'd like to avoid having an Rc<MessageThunk>
here if possible. I.e. that all the provided routing information and async execution is in either View::build/rebuild
(IIRC that's currently the case for all other async views).
I've used an Option<impl Future>
in #452, maybe more like this?
The
MemoizedStream
view is is basically aMemoizedAwait
view that accepts a stream and invokes the callback for each stream item received.Since the implementation is almost the same, the two views are just wrappers for the private
MemoizedInner
struct.If the approach is okay, I can also add an example.