Unlike the example in the official documentation, it actually compiles and works.
The project is a demo of a rotating cube on a web page in WebGL, so it might be interesting for you as a whole.
Note that you can't really make a loop in WASM, because the browser needs to do its own event handling in the same thread. You can only work with callbacks, such as the one provided by request_animation_frame.
However, I think what @LukeMiloch is referring to is that requestAnimationFrame() doesn't definitively run at 60fps.. if the browser gets busy, it can run less frequently - so the value of perf.now() - start_time can be very large, leading to odd behavior in a game.
Of course visually it won't matter since the rendering can only happen on a repaint anyway - but for collision detection and things like that, updating based on time passed to a low fps render tick (and the big gap of deltatime due to that) is a problem.
Yes, request_animation_frame also isn't called at all when the tab is not the frontmost in that window. Additionally, on my 144Hz monitor, it's probably going to called way more than 60 times a second.
However, nothing stops you from scheduling another fixed-duration timer for non-drawing things like physics. The lifetimes might get a little tricky then, though. You're going to have to use Rc<RefCell<_>> a lot for that.
I think I'm going to try my hand at porting that MainLoop example into awsm sometime in the next couple weeks or so...
But in the meantime I did export an easy-to-use function takes a callback and calls it every requestAnimationFrame tick with total time, delta time, and elapsed time. It returns a cancel function: awsm::tick::start_raf_ticker_timestamp - Rust
Usage is like:
let cancel_fn = start_raf_ticker_timestamp(|time_stamp| {
let Timestamp {time, delta, elapsed} = time_stamp;
});
(currently, if you want to cancel from within the loop you can do that but it's a little tricky... there's a demo here)