#wasm http? - Can you help me get this code working?

45 messages · Page 1 of 1 (latest)

slender kite
#

I don't believe there is a simple example for an http request with bevy?
I'm looking to complete a minimum viable wasm example sending an http call and grabbing the result, and setting the response to text.

fn counter_system2(mut query: Query<&mut Counter>, mut query2: Query<&mut Text>) {
    for mut fieldd in query.iter_mut() {
        if fieldd.c_name == String::from("counter_two") {
            fieldd.c += 2;
            if fieldd.c % 100 == 0 {
                let request = ehttp::Request::get("http://localhost:8081/test");
                ehttp::fetch(request, move |result: ehttp::Result<ehttp::Response>| {
                    let v: Value = serde_json::from_slice(&result.unwrap().bytes).unwrap();
                    for mut text in &mut query2 {
                        text.sections[0].value = format!("new value from http req: {}", v);
                    }
                });
            }
        }
    }
}

Can someone show me how something like this could work with bevy? This doesn't work because I'm trying to use query2 inside the move.

broken ravine
#

you should use two systems one for sending the request and the second for receiving the response. You can do this by using a channel. In the first system you would pass the sending side of the channel into the closure and store the receiving end in a resource. In the second system you poll the receiving end once and then set the text when you get a response

slender kite
#

are there bevy examples with the use of channels?

slender kite
#

@broken ravine you do mean mpsc channels?

broken ravine
#

yeah

slender kite
# broken ravine yeah

@broken ravine im finding it complicated to complete a minimum viable code sample with mpsc channels with http requests and bevy.. do you figure there's an example somewhere?

broken ravine
#

probably a little messy since it's a jam game

slender kite
#

Still tackling this problem> Not giving up yet.

@broken ravine I'm sort of perplexed by why you are doing sets of channels..
and then when you call run_async you are putting in the disparate rx/tx pairs.

Did you look at https://github.com/bevyengine/bevy/blob/latest/examples/async_tasks/async_compute.rs
AsyncComputeTaskPool as a possible solution? (Unsure if this is a good method for this or not).

GitHub

A refreshingly simple data-driven game engine built in Rust - bevy/async_compute.rs at latest · bevyengine/bevy

broken ravine
#

I'm using tokio, which has it's own tasks and threading separate from bevy.

#

also jumping through some hoops to make it work on wasm

#

so I use one channel to initiate a request and another to get the response

#

with the lib you're using you might be able to just use one for the response

slender kite
#

in the example via the link above they are using Task<Transform> to store the moved result via commands.spawn(ComputeTransform(task));

If i was storing a string or json response and not a Transform.. what method would one use?
Trying to use Task<String> doesn't work.

#

nvm removing "Default" fixed this issue

#

interesting
when i compile i get an error about my string being a faketask

#

so i guess piggy backing off the command.spawn won't work here.. how would i make this a real task?

slender kite
broken ravine
#

be aware that bevy_webgl2 is no longer necessary

slender kite
#

@broken ravine do you know how/why Res<AsyncComputeTaskPool is used without being declared as a resource? I saw another older example doing this as well.

#

im guessing this is how bevy worked in previous versions?

#

i also find it interesting that
type DataGetter = Worker<(), anyhow::Result<Data>>;
is being used as a resource in their example

broken ravine
#

The task pools got changed to a global static around 0.7 or 8

#

this example looks pretty old. Probably from around 0.4

#

basic idea is still the same though

#

you detach the task and coordinate with it through channels

slender kite
#

the thing i keep getting tripped over is errors when i try to put the channel reference inside of the "async move" closure I'll get something along the lines of which does not implement the `Copy` trait

#

im storing the channel as a bevy resource

broken ravine
#

You can just clone them

slender kite
broken ravine
#

You won't be able to copy the struct

#

Just call .clone() on it

slender kite
# broken ravine Just call .clone() on it
fn send_counter(
    mut commands: Commands,
    comm_channels: ResMut<CommChannels>,
    mut query: Query<&mut Counter>,
) {
    for mut fieldd in query.iter_mut() {
        if fieldd.c_name == "sender" {
            fieldd.c += 1;
            if fieldd.c % 100 == 0 {
                let pool = AsyncComputeTaskPool::get();
                let task = pool
                    .spawn(async move {
                        let body = reqwest::get("http://localhost:8081/test")
                            .await
                            .unwrap()
                            .text()
                            .await
                            .unwrap();

                        comm_channels.tx.clone().try_send(body);
                    })
                    .detach();
            };
        };
    }
}
#

this is probably really bad code.. but just trying to understand

#
move occurs because `comm_channels` has type `bevy::prelude::ResMut<'_, CommChannels>`, which does not implement the `Copy` trait
broken ravine
#

Try cloning it outside of the closure

slender kite
#

damn..

#

it worked

#

you're the missing shoe i was looking for in my life

#
    let cc = comm_channels.tx.clone();
                let task = pool
                    .spawn(async move {
                        let body = reqwest::get("http://localhost:8081/test")
                            .await
                            .unwrap()
                            .text()
                            .await
                            .unwrap();

                        cc.try_send(body);
                    })
                    .detach();
#

didn't realize that would make a difference

#

i also don't need to "detach" so not sure what that gets me

broken ravine
#

so what going on there is that rust is trying to implicitly copy comm_channels into the closure, but comm channels is a reference that only lives for the lifetime of the system and so can't actually be copied into the static future. Cloning outside the async closure creates an owned value that can be moved into the future.

#

I think on wasm detach is a no-op, and the tasks are automatically detached. So the detach is only for other platforms, where dropping the Task cancels the future