Цепочка обещаний через #flatMap () в Play Controller-Action

1

Я хотел бы спросить, подходит ли то, что я делаю, или если есть лучший/более эффективный/более простой способ.

Сценарий:

  1. Пользователь регистрируется с адресом электронной почты и паролем, перенаправляется в login() -action
  2. Если пользователь уже находится в БД и имеет хэширование пароля, выполните аутентификацию с помощью DB-пользователя и верните результат-обещание
  3. Если пользователь не находится в БД или не имеет пароля, выполните запрос веб-службы с данными входа и проанализируйте статус из ответа → верните Status -instance
  4. Проверьте статус пользователя и верните результат-обещание

Код:

public Promise<Result> login() {
    Promise<User> 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<Status> 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. Я понял использование обещаний и плоских карт, правильно ли я использую его или "чрезмерно использую" его?
Теги:
playframework
promise
nonblocking
playframework-2.0

1 ответ

2
Лучший ответ

.flatMap - это когда некоторое возвращаемое значение функции, которую вы ему даете, возвращает само Promise. Если все, что вы делаете, это возврат не фьючерсов, то вы можете просто использовать .map, поэтому последнее .flatMap, похоже, не должно быть .flatMap поскольку вы просто обертываете все значения результатов в Promise.pure, с помощью .map вы можете просто верните эти значения без дальнейшего бокса в Promise.

Функция, которую вы даете userPromise.flatMap с другой стороны, вернет Promise поэтому она должна быть flatMap, иначе она в свою очередь вернет Promise<Promise<Result>> которую вы не можете вернуть из действия вашего контроллера.

  • 0
    По сути, все, что вы видите, является частью функции, которую я даю userPromise.flatMap , поэтому я боюсь, что последний .flatMap не может быть картой, иначе возвращаемые типы не совпадают. НО: является ли flatMap на моем holderWithParams.get() необходимым для использования Status в результате, или это может быть просто map ? Это та часть, в которой я не совсем уверен, я думал, что это должен быть flatMap из-за выравнивания до одного Обещания для Status .
  • 0
    Чтобы упростить мой вопрос: является ли тип возврата ( Promise<A> и A ) единственной разницей между flatMap и map ? Если так, то я действительно мог бы сэкономить последние flatMaps , я подумал, что это необходимо, если я хочу повторно использовать возвращенный объект из-за «выравнивания» (что бы это ни значило).
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню