如何使用功能方法从内部范围更新值?

How to update values from an inner scope with a functional approach?

我有一个案例,我从客户端获取两个字符串的数组,然后在服务器端映射它们,为它们中的每一个打开一个流。 (在代码示例中,我使用 setInterval 而不是真实的数据流,以使事情尽可能简单。)

我还在一个对象中重组了这些数据,这样我就可以保留稍后更新的值。每当 setInterval 被触发时,我都会增加与我正在映射的迭代对象对应的键的值。

const stream = (arr) => {

    // arr = ['firstValue', 'secondValue']

    // the object to store the values which will be sent to the client
    const restructure = {
        [arr[0]]: 0,
        [arr[1]]: 0
    }

    arr.map((i) => {
        // setInterval as a placeholder stream
        setInterval(() => {
            restructure[i]++
            // instead of logging, the updated object is sent to client
            console.log(restructure)
        }, 2000)
    })
}

增加值后,我将更新后的对象发送回客户端。显然这可行,但我想用更实用的方法来执行此更新操作。

我已经尝试了一些来自 Ramda 和 Lodash/Fp 的方法,但似乎不可能从不同的范围更新对象。

通常最终发生的事情是值被颠簸,然后在下一个时间间隔恢复到原来的值。

是否有一种可行的方法可以通过某种功能 setState 从内部范围更新此数据?

Ramda 的设计原则是永不修改用户数据。这并不意味着您不能使用 Ramda 这样做,但 Ramda 函数本身不会帮助您这样做。这是故意的;不可变数据结构是函数式编程的重要概念之一。

关于您的示例,我注意到的第一件事是您的 stream 函数没有 return 任何东西。同样,这在 FP 中是一件奇怪的事情。

现在,关于在您的函数中使用 Ramda,您可以先使用 let restructure = fromPairs(map(key => [key, 0], arr))

在您的 setInterval 中,您可以自己重置 restructure 值,例如 restructure = evolve({[i]: R.inc}, restructure).

将它们放在一起,我们可以得到与您的示例类似的东西

const stream = (arr) => {
  let restructure = fromPairs(map(key => [key, 0], arr));
  R.map((key) => {
    setInterval(() => {
      restructure = evolve({[key]: R.inc}, restructure            
      console.log(restructure);
    }, 2000)
  }, arr)

  return () => restructure
}

同样,Ramda 实际上并没有就地更新那个变量。但它肯定不会阻止你重新分配它。

您可以在 Ramda REPL.

中看到它的细微变化