выполнить задание Flutur с помощью Sancuary Either - PullRequest
0 голосов
/ 05 ноября 2019

У меня есть такой канал

const asyncFn = (x) => {
    return Future.tryP(() => Promise.resolve(x + ' str2'))
};

const pipeResult = S.pipe([
    x => S.Right(x + " str1"), // some validation function
    S.map(asyncFn),
])("X");

pipeResult.fork(console.error, console.log);

Я хочу выполнить некоторую асинхронную операцию в asyncFn. Проблема в том, что когда у меня есть Right в качестве ввода, я могу больше его разветвлять.

Когда я регистрирую pipeResult, я вижу это:

Right (tryP(() => Promise.resolve(x + ' str2')))

Как я могу это сделать?

1 Ответ

1 голос
/ 05 ноября 2019

Either a b и Future a b оба способны выражать неудачу / успех. При работе с асинхронными вычислениями обычно лучше использовать Future a b, а не Future a (Either b c). Более простой, более плоский тип требует меньше отображений: S.map (f), а не S.map (S.map (f)). Другое преимущество состоит в том, что значение ошибки всегда находится в одном и том же месте, тогда как Future a (Either b c) и a, и b представляют собой неудачные вычисления.

Мы можем, тем не менее, уже иметь функцию проверки, которая возвращаетили. Например:

//    validateEmail :: String -> Either String String
const validateEmail = s =>
  s.includes ('@') ? S.Right (S.trim (s)) : S.Left ('Invalid email address');

Если у нас есть значение fut типа Future String String, как мы можем проверить адрес электронной почты, который может содержать fut? Первое, что нужно попробовать, это всегда S.map:

S.map (validateEmail) (fut) :: Future String (Either String String)

Было бы неплохо избежать такого вложения. Чтобы сделать это, нам сначала нужно определить функцию от Either a b до Future a b:

//    eitherToFuture :: Either a b -> Future a b
const eitherToFuture = S.either (Future.reject) (Future.resolve);

Теперь мы можем преобразовать функцию, возвращающую любой из них, в функцию, возвращающуюся в будущем:

S.compose (eitherToFuture) (validateEmail) :: String -> Future String String

Давайте вернемся к нашему использованию S.map:

S.map (S.compose (eitherToFuture) (validateEmail)) (fut) :: Future String (Future String String)

У нас все еще есть вложение, но теперь внутренний и внешний типы оба Future String _. Это означает, что мы можем заменить S.map на S.chain, чтобы избежать вложения:

S.chain (S.compose (eitherToFuture) (validateEmail)) (fut) :: Future String String
...