What's the proper way to call a async function in another async function?

Viewed 273

I try write my first rust web demo with actix-web. I copied the example in actix-web welcome web page and changed it as below:

use actix_web::{get, App, HttpRequest, HttpServer, Responder};
use std::io::Result;

#[get("/{name}")]
async fn greet(req: HttpRequest) -> impl Responder {
    let name = req.match_info().get("name").unwrap_or("World");
    format!("Hello {}!", &name)
}

#[get("/")]
async fn greet2(req: HttpRequest) -> impl Responder {
    greet(req)
}

#[actix_web::main]
async fn main() -> Result<()> {
    HttpServer::new(|| App::new().service(greet).service(greet2))
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
}

I'm trying to call async function "greet" in another async function "greet2" and got compile error:

   Compiling rust-http-demo v0.1.0 (/Users/xxx/codes/practice/rust-http-demo)
error[E0618]: expected function, found `greet`
  --> src/main.rs:12:5
   |
4  | #[get("/{name}")]
   | ----------------- `greet` defined here
...
12 |     greet(req)
   |     ^^^^^-----
   |     |
   |     call expression requires function

For more information about this error, try `rustc --explain E0618`.
error: could not compile `rust-http-demo` due to previous error

I realized async function cannot be called as normal function, but the compiler's message puzzles me. What does it mean and how can I fix it?

1 Answers

An async function returns a Future, you need to await the future to get the result. In your case the Responder:

#[get("/")]
async fn greet2(req: HttpRequest) -> impl Responder {
    greet(req).await
}

But this may not even be enough. get is a macro that modifies your function definition. Look source.

You can not call it itself. Would be better to take the implementation outside of the macro wrapped call:

async fn greet_prime(req: HttpRequest) -> impl Responder {
    let name = req.match_info().get("name").unwrap_or("World");
    format!("Hello {}!", &name)
}

#[get("/{name}")]
async fn greet(req: HttpRequest) -> impl Responder {
    greet_prime(req).await
}

#[get("/")]
async fn greet2(req: HttpRequest) -> impl Responder {
    greet_prime(req).await
}
Related