如何在使用fp-ts时从错误处理函数中访问ReaderTaskEither中的变量?

huangapple go评论75阅读模式
英文:

How to get access to a variable in a ReaderTaskEither from an error handling function using fp-ts?

问题

我有这段代码,其中我使用了ReaderTaskEither

export const AddUserToTeam = ({ userId, teamId }: AddUserToTeamDto) => {
    return pipe(
        // 👇 使用了ReaderTaskEither
        Do,
        bind("deps", () => ask<Deps>()),
        bind("tx", ({ deps }) => fromTask(deps.createTransaction())),
        bind("addToTeams", ({ deps, tx }) => {
            return fromTaskEither(
                // ...
            );
        }),
        bindW("result", ({ deps, tx }) => {
            return fromTaskEither(
                deps.dispatcher.create(
                    // ...
                )({ tx })
            );
        }),
    );
};

我创建了一个交互式事务(tx)作为pipe的一部分。我的问题是,如果出现错误,我想通过使用foldmapLeft来在tx上调用rollback,但我在任何地方都无法访问包含tx的上下文。我应该如何做才能保留对tx的引用?

请注意,我不能将tx作为Deps的一部分,因为我不打算在所有地方都使用事务(它们是可选的)。

英文:

I have this code where I use ReaderTaskEither:

export const AddUserToTeam = ({ userId, teamId }: AddUserToTeamDto) =&gt; {
    return pipe(
        // &#128071; Uses ReaderTaskEither
        Do,
        bind(&quot;deps&quot;, () =&gt; ask&lt;Deps&gt;()),
        bind(&quot;tx&quot;, ({ deps }) =&gt; fromTask(deps.createTransaction())),
        bind(&quot;addToTeams&quot;, ({ deps, tx }) =&gt; {
            return fromTaskEither(
                // ...
            );
        }),
        bindW(&quot;result&quot;, ({ deps, tx }) =&gt; {
            return fromTaskEither(
                deps.dispatcher.create(
                    // ...
                )({ tx })
            );
        }),
    );
};

and I create an interactive transaction (tx) as part of the pipe. My problem is that I'd like to call rollback on tx in case there was an error by using a fold or a mapLeft but I don't have access to the context that contains tx in either. How should I do this in order to retain a reference to tx somewhere?

Note that I can't make tx part of Deps because I'm not going to use transactions everywhere (they are opt-in).

答案1

得分: 1

你可以在创建了tx之后,在一个“嵌套级别”中执行它。从你的代码片段中:

export const AddUserToTeam = ({ userId, teamId }: AddUserToTeamDto) => {
  return pipe(
    Do,
    bind("deps", () => ask<Deps>()),
    bind("tx", ({ deps }) => fromTask(deps.createTransaction())),
    chain(({ deps, tx }) =>
      pipe(
        fromTaskEither(/*...*/),
        chain((addToTeams) =>
          fromTaskEither(deps.dispatcher.create(/*...*/)({ tx })),
        ),
        orElse((e) => fromTaskEither(tx.rollback())),
      ),
    ),
  );
};

我不知道tx.rollback的返回类型是什么,所以我猜测了一下。

英文:

You can do it in a "nested level", after you created tx. From you snippet:

export const AddUserToTeam = ({ userId, teamId }: AddUserToTeamDto) =&gt; {
  return pipe(
    Do,
    bind(&quot;deps&quot;, () =&gt; ask&lt;Deps&gt;()),
    bind(&quot;tx&quot;, ({ deps }) =&gt; fromTask(deps.createTransaction())),
    chain(({ deps, tx }) =&gt;
      pipe(
        fromTaskEither(/*...*/),
        chain((addToTeams) =&gt;
          fromTaskEither(deps.dispatcher.create(/*...*/)({ tx })),
        ),
        orElse((e) =&gt; fromTaskEither(tx.rollback())),
      ),
    ),
  );
};

I don't know what's the return type of tx.rollback, so I made it up.

huangapple
  • 本文由 发表于 2023年7月10日 20:58:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76653984.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定