代码之家  ›  专栏  ›  技术社区  ›  Avrohom Yisroel

LanguageExt-当Match lambda是异步的时,如何避免双重等待?

  •  1
  • Avrohom Yisroel  · 技术社区  · 11 月前

    我在这里使用了一个愚蠢的简单示例,以避免与真实案例的细节混淆,并提供一个最小的完整示例。只要您引用了 LanguageExt.Core Nuget package ,并添加了以下内容 using s

    using LanguageExt;
    using static LanguageExt.Prelude;
    

    想象一下,我有一个API float ,并返回加倍的平方根。我有以下助手功能。。。

    static Either<string, double> Sqrt(double d) =>
      d >= 0.0
        ? Math.Sqrt(d)
        : "Error: Negative number";
    
    static Either<string, double> Double(double d) =>
      d > 10.0
        ? "Error: Too big to double"
        : 2 * d;
    

    如果成功,我的API端点将返回一个格式为“Result:23.3”的字符串,否则返回一个错误。

    我把这些连接在一起如下。。。

    public static string Calc(double d) =>
      (from res1 in Sqrt(d)
       from res2 in Double(res1)
       select res2)
      .Match(res => $"Result: {res}",
        err => err);
    

    这是意料之中的事。显然,我的真实代码会有更多 from 子句比这个多,但我尽量保持简单。

    现在,假设(更现实的是)helper函数是 async ,那么我需要修改我的端点,使其看起来像这样。。。

    public static async Task<string> Calc(double d) =>
      await (from res1 in Sqrt(d).ToAsync()
             from res2 in Double(res1).ToAsync()
             select res2)
        .Match(res => $"Result: {res}",
          err => err);
    

    再说一遍,一切都好。

    在一边 我从阅读Paul Louth在LanguageExt期刊上的一些代码中获得了上面的编码风格。如果有更好的方法,请随时提出建议。我并不声称自己是这方面的专家。

    但是,现在如果出现错误,我想记录它们,发送电子邮件等,所以第二个lambda到 Match 方法需要 异步 。为了避免编译器错误,我需要制作第一个 异步 以及,然后 await 结果。。。

    public static async Task<string> CalcAsync2(double d) =>
      await await (from res1 in Sqrt(d).ToAsync()
                   from res2 in Double(res1).ToAsync()
                   select res2)
        .Match(async res => $"Result: {res}",
          async err => {
            // Log the error, send an email, etc (async);
            return err;
          });
    

    这开始让人觉得我做这件事完全错了。也许我错了,但等待等待的任务似乎并不正确。

    有人能在这里发表评论吗?如果任何一个helper方法返回了 Left ,但如果所有 异步 工作(事实上,尽可能多的工作)是在 从…起 克吕兹,留下lambdas Math 只需要返回值。

    1 回复  |  直到 11 月前
        1
  •  2
  •   Guru Stron    11 月前

    只需使用 MatchAsync :

    static Task<string> CalcAsync2(double d) =>
         (from res1 in Sqrt(d).ToAsync()
             from res2 in Double(res1).ToAsync()
             select res2)
         .MatchAsync(res => Task.FromResult($"Result: {res}"),
             async err =>
             {
                 await Task.Delay(1);
                 // Log the error, send an email, etc (async);
                 return err;
             }
         );
    
    推荐文章