Actix-web:将消息发送到数据库处理程序,有条件地将消息发送到第二个处理程序

Actix-web: send message to db handler, conditionally send message to second handler

我正在尝试向一个数据库处理程序发送消息,然后根据结果向第二个处理程序发送消息,或者 return 第一个处理程序出现错误。

到目前为止我想出的办法都行不通; rustc 说 match arms have incompatible types

expected struct 'futures::future::and_then::AndThen', found enum 'std::result::Result'

state
    .db
    .send(...)
    .from_err()
    .and_then(|res| match res {
        Ok(response) => {
        // Do some additional logic here
        state
        .db
        .send(...)
        .from_err()
        .and_then(|res| match res {
            Ok(response) => Ok(HttpResponse::Ok().json(response)),
            Err(err) => Ok(HttpResponse::InternalServerError().body(err.to_string()))
            }) 
        },
        Err(err) => Ok(HttpResponse::InternalServerError().body(err.to_string()))
    })
    .responder()

问题如何在actix-web中完成这个?

你快到了。

使用 match 时,所有武器必须产生相同的类型。在你的情况下,一个是与 and_then 结合的未来,另一方面,你有一个 result.

此外,除非你的send()函数returns类型impl Future<Item = Result<R, E>, Error = E>,否则match是完全多余的。 and_then 作为参数 Item,而不是 Result<Item, Error>

所以,整个事情可以简化为:

state
  .db
  .send(...)
  .from_err()
  .and_then(|res| state.db.send(...).from_err())
  .then(|res| match res {
     Ok(response) => Ok(HttpResponse::Ok().json(response)),
     Err(err) => Ok(HttpResponse::InternalServerError().body(err.to_string()))
   })
   .responder()

不过,我们假设您的类型是正确的。您可以轻松地将 Result 转换为 futurefuture::result ,如下所示:

state
    .db
    .send(...)
    .from_err()
    .and_then(|res| future::result(res).from_err())
    .and_then(|res| 
        // Do some additional logic here
          state
          .db
          .send(...)
          .from_err()
     )
     .and_then(|res| future::result(res).from_err())
     .then(|res| match res {
       Ok(response) => Ok(HttpResponse::Ok().json(response)),
       Err(err) => Ok(HttpResponse::InternalServerError().body(err.to_string()))
      })
     .responder()

那里的沙盒上有一个示例:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=6801886b02081160e268f395bcc1ad6c