通过Play Controller-Action中的#flatMap()链接Promise

我想问一下我的工作是否合适,或者是否有更好/更有效/更简单的方法。

场景:

  1. 用户使用电子邮件地址和密码登录,将路由到login() – 操作
  2. 如果用户已在数据库中并且密码已经过哈希处理,请使用DB-user进行身份validation并返回结果承诺
  3. 如果用户不在数据库中或没有密码哈希,请使用login-data执行Web服务请求并从响应中解析状态 – >返回Status -instance
  4. 检查用户的状态并返回结果承诺

码:

 public Promise login() { Promise userPromise = Promise.promise(() -> User.findByName(login.emailAddress)); return userPromise.flatMap(user -> { if (user != null && user.hasPassword()) { if (user.authenticate(login.password)) { return Promise.pure(ok("login successful"))); } // password did not match return Promise.pure(unauthorized()); } // user has no password-hash stored, so do a webservice-request instead final WSRequestHolder holderWithParams = getWSRequestHolderForUserStatus(login.emailAddress, login.password); final Promise statusPromise = holderWithParams.get().flatMap(this::parseStatusFromResponse); return statusPromise.flatMap(status -> { if (status != null) { if (status.isValid()) { return Promise.pure(ok("login successful"))); } // not a valid status, return unauthorized return Promise.pure(unauthorized()); } return Promise.pure(badRequest("response parsing error"); }); }); } 

我的问题:

  1. 我做错了什么或者没有必要,如果是的话:什么是正确的,更容易的或更有效的方式?
  2. 我是否理解Promise和flatMaps的使用,我是正确使用它还是“过度使用”它?

.flatMap用于当你给它的函数的某些返回值返回一个Promise本身。 如果您所做的只是返回非期货,那么您可以使用.map ,因此最后的.flatMap似乎不需要是.flatMap因为您只需将所有结果值包装在Promise.pure ,使用.map即可只需返回这些值而无需在Promise中进一步装箱。

另一方面,你给userPromise.flatMap的函数将返回一个Promise因此它必须是一个flatMap,否则它将返回Promise> ,你无法从你的控制器动作返回。