Rust WASM gets stuck on await when using IndexedDb API

I'm trying to use async in rust wasm to interact with the IndexedDb API. However, the code seems to be stuck on an await. I should be leveraging the async runtime in the browser, but I'm puzzled as to why it would get stuck.

Here's the test code I wrote:

// index.js
import init from "./js/test_wasm.js";
import { open } from "./js/test_wasm.js";

async function main() {
  console.log("initializing....");

  await init();
  console.log("js opening...");

  const db = await open("test.db");

  console.log("js opened db:", db);
}

main();
// in rust
#[wasm_bindgen]
pub async fn open() {
    let window = web_sys::window().expect("no global `window` exists");
    let indexed_db = window
        .indexed_db()
        .expect("no global `indexedDB` exists")
        .unwrap()
        .clone();

    // convert request into JsFuture
    let promise = js_sys::Promise::new(&mut |resolve, reject| {
        let request = indexed_db
            .open_with_u32("embodied_db", 4)
            .expect("failed to open db");

        request.set_onsuccess(Some(&resolve));
        request.set_onerror(Some(&reject));
    });

    logger::log("request open db");

    // * it seems to get stuck here *
    let open_db_request = JsFuture::from(promise).await.expect("failed to open db");

    logger::log("opening db");

    let db = open_db_request
        .dyn_into::<IdbDatabase>()
        .expect("failed to open db");

    logger::log("creating object store");

    let store = db
        .create_object_store("txlog")
        .expect("failed to create store");

    logger::log("  created store");
}

This is the console log in the browser

initializing.... index.js:5:11
InstallTrigger is deprecated and will be removed in the future. commons.js:2:1344767
js opening... index.js:8:11
request open db

I've been stuck on this for a while, and would appreciate any insight. Thanks!

One of the other events may be firing instead. Open requests can receive blocked and upgradeneeded events instead of success or error events.

This likely isn't a problem yet in your code, but it's worth noting that JS promises don't play nicely with indexedDB[1]. IndexedDB transactions close if no new requests are submitted in the current run loop iteration, and async functions don't run until the next run loop iteration. That can lead to some extremely hard to debug race conditions.


  1. I know there were some proposals to fix this, but as far as I know they haven't been adopted ↩︎

Wait, if other events like that are firing, does that mean that if there’s no handler for the event, rust async just hangs?

I had assumed that any event you don’t care about, you wouldn’t need to provide a handler like in JavaScript.

If you write the exact same code in JS the same thing will happen, the promise never resolves because you only call resolve on the success event, and reject on the error event

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.