I am building a Wasm component using componentize-js running on a Rust host. I provide a kv (key value db) capabilities interface to the guest where get and set perform outbound database calls on the host side.
Here is a part of the wit:
// kv store interface - host provides these capabilities
interface kv {
// Get value from kv store, returns none if key not found
get: func(key: string) -> option<string>;
// Set value in kv store
set: func(key: string, value: string);
}
Is there any way to expose these functions as non-blocking so they do not freeze the js event loop?
I understand from the README that async imports are not yet supported. I experimented with the pollable pattern, but it appeared to still block execution. I would prefer to keep the db logic in the host rather than moving it to js.
Am I missing a specific pattern or workaround to achieve behavior similar to fetch?
I think at present with what is available in P2, you need to write the machinery to do the checking on your own here, with wasi:io and friends (and then on the JS side add the appropriate Promises, setTimeouts, etc to play nicely with the StarlingMonkey event loop). This would mean changing the types that are returned from the interface itself rather than "simply" making the whole operation async in a way that JS could natively understand.
Preview3 work introduces structured concurrency but it's very much focused on host implementation now (which is still not done just yet on the Jco side) -- the guest-side work (i.e. changes to ComponentizeJS/StarlingMonkey) that might make this kind of async-aware interop automatic I don't think are close to completion just yet.
Once P3 work is in the JS guest ecosystem, you should be able to write future<t> and stream<t> classes that will turn into Promises and Streams and be much easier to use without blocking on the guest side naturally.
Like i said though, you can write these abstractions around the wasi:io bits now if you'd like.
There's a basic example that you can use/build upon in jco-std:
Thanks @Victor Adossi for the reply. I have implemented some machinery as you suggested but I think it doesn't play well... So I have used WASI pollable for that, my client is returning futures, guest side polls for a result, parallel operations works. The total execution time looks almost identical as the version with a client on a guest side. The problem is event loop starvation, I need to experiment more...
I dig more and It wasn't event loop starvation, what I have observed was blocking nature of the poll.
When I do await Promise.all([kv1, kv2, ...]) it blocks event loop till the first resolve. The difference with fetch is that it blocks in small chunks. kv operation is atomic, where fetch has different granularity: dns done, connect done, body chunk...
Last updated: Dec 06 2025 at 07:03 UTC