如何避免闭包中布尔标志的突变?

How do I avoid mutation of a boolean flag in a closure?

提问人:Aaron 提问时间:1/28/2022 最后编辑:ChrisAaron 更新时间:1/29/2022 访问量:121

问:

假设我在 TypeScript 中有这个函数,它使用闭包来管理状态:

  1. firebase 分析实例
  2. guid(用户 ID)。

该函数返回另一个函数,该函数接受 Firebase 方法的参数。我只想在 firebase 上设置一次用户 ID,所以我使用布尔标志来检查以前是否做过。logEvent

有没有办法在不改变变量的情况下做到这一点?或者有没有办法在没有需要突变的布尔标志的情况下实现这一点?guidSet

我知道,在像这样的小事情中,也许可读性超过了不改变变量的“教条”。此外,函数之外的任何事物都无法观察到这一事实使这种突变不那么“危险”,但无论如何,我感兴趣的是如何在不从技术上改变我的函数内的任何内容的情况下实现这一目标:guidSetLogger

import analytics from "@react-native-firebase/analytics";

function Logger(): Function {
  const analyticsInst = analytics();
  let guidSet: boolean;
  return (key: string, data?: any, guid?: string | null) => {
    if (!guidSet && guid) {
      guidSet = true;
      analyticsInst.setUserId(guid);
    }
    analyticsInst.logEvent(key, data);
  };
}
TypeScript 函数编程 闭包 状态

评论

1赞 Mark Seemann 1/28/2022
您通常会从函数返回新的布尔值。当函数已经返回“其他”值时,您将返回一个元组。这基本上就是作家单子。
0赞 Aaron 1/28/2022
您能扩展或举个例子吗?如果你回答,我会把它标记为已接受。
1赞 1/28/2022
我假设闭包是由一个事件调用的,并且您希望被调用任意次数,但只能调用一次。因此,基本上你在一个有效的、不纯洁的环境中工作,并希望避免一个不纯洁的方面,即重新分配。AFAIK,这行不通。您的 lambda 甚至不返回值。也许您可以拆分这两个操作并将它们分配给不同的事件处理程序,其中一个事件处理程序仅触发一次?logEventsetUserId
0赞 Aaron 1/28/2022
我认为你是对的。lambda 的目的是副作用。因此,在事物的方案中,一个变异的“私有”变量肯定是绝对可以的。
1赞 Mark Seemann 1/29/2022
据我所知,看起来像是副作用(即不纯)的行为。只要动作是这样做的,就没有理由避免突变,因为即使你可以消除那个特定的突变,整体动作也会保持不纯。analyticsInst.setUserIdanalyticsInst.logEventLoggerguidSet

答:

0赞 Noob Life 1/28/2022 #1

这行得通吗?

import analytics from "@react-native-firebase/analytics";

function Logger(guid: string): Function {
  const analyticsInst = analytics();
  analyticsInst.setUserId(guid);

  return (key: string, data?: any) => {
    analyticsInst.logEvent(key, data);
  };
}

评论

0赞 Aaron 1/28/2022
不,因为我不想在调用外部函数时设置 guid。