代码之家  ›  专栏  ›  技术社区  ›  Flame_Phoenix

如何正确登录避难所/Fluture?

  •  2
  • Flame_Phoenix  · 技术社区  · 7 年前

    背景

    我有一个函数,叫做 logInfoAsync . 让我们考虑一下这个函数通过网络向日志服务器发送一些信息。为了解决这个问题,我们假设函数的实现如下:

    const logInfoAsync = logger => message =>
        new Promise( ( resolve, reject ) => {
            setTimeout( () => {
                //random fail reason.
                if( message.length > 10 ){ 
                    reject( "We have angered the Gods. Message is too big!" );
                    return;
                }
                logger(message);
                resolve();
            }, 2000 );
        })
    

    用法:

    const myLog= logInfoAsync( console.log );
    myLog("Hello world!") // Rejected: "We have angered the Gods. Message is too big!"
    myLog("Hello") // Resolved: "Hello"
    

    问题

    到现在为止,一直都还不错。我们有一个标准的记录器,有时工作,有时它激怒了神。

    现在,假设我们有一个序列 async 计算:

    const { Future } = require("Fluture");
    
    const myLogF= Future.encaseP( logInfoAsync( console.log ) );
    
    //request.get returns a Future and so does saveDB
    request.get("http://mywebsite.com")
        .chain( response => myLogF(`res is: ${res}`) )
        .chain( saveDB )
        .chain( ( ) => myLogF("Saved!") )
        .fork(
            err => console.log(`Something failed badly!: ${err}`),
            ( ) => console.log("Data saved to Olympus with great success!")
        );
    

    在这个例子中,如果伐木工人激怒了众神会发生什么? 好吧,我们没能保存数据!也许请求进行得很顺利,也许数据是有效的,但由于记录器失败,我们搞砸了!

    研究

    现在,一个可能的解决方案是 Fluture.bimap 在每一个日志之后。 这太可怕了 .

    我不想让我的日志比现在更具攻击性,我也绝对不想让我的代码乱丢承诺式的东西 try/catch S.

    不幸的是,这是我唯一能想到的。。。我认为最好的选择是 备份记录器 ,例如, console.error 如果 myLogF 失败了,但我最理想的情况是我希望这是看不见的。

    应用程序根本不应该知道它正在被记录!

    问题

    因此,根据这个片段,我有以下问题:

    1. 如果日志失败,您将如何保持链的运行?
    2. 如何使日志失败和恢复对应用程序不可见(而不将其与( 尝试/抓住 )?
    3. 日志最常用的模式是什么?
    1 回复  |  直到 7 年前
        1
  •  2
  •   Avaq    7 年前

    我会做一个 tap 专门用于期货的功能,例如:

    const always = x => y => x
    const tapF = f => x => f(x).fold(always(x), always(x))
    

    这种实现 tapF 期望 f 返回一个未来,它将强制它使用原始输入值进行解析。

    然后它可以用于日志记录,例如:

    request.get("http://mywebsite.com")
    .chain( tapF(res => myLogF(`res is: ${res}`)) )
    .chain( saveDB )
    .chain( tapF(() => myLogF("Saved!")) )
    

    现在这个表达式的结果完全独立于 tapF公司 功能。

    我认为这应该回答你的前两个问题。最后一个:“日志最常用的模式是什么?”,我不确定。有几个模式,我可以想到两个:

    • 在表示副作用的Monad中作为副作用记录。这就是我们所做的 tapF公司 .
    • 使用Writer Monad收集内存中的日志,并在程序的边缘写入它们。我没有这方面的经验。
    推荐文章