用Sancuary Either执行Fluture任务

时间:2019-11-05 07:19:23

标签: javascript functional-programming sanctuary fluture

我有这样的烟斗

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 个答案:

答案 0 :(得分:2)

Either a bFuture 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 bFuture 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