将函数组合成更具“功能性”的JavaScript

时间:2018-05-25 12:30:28

标签: javascript functional-programming composition

我有一些(伪)代码,如下所示

const { search, hash } = window.location // get search / hash from url
  const tokenParts = queryParams(search || hash) // create an object
  const { id_token, access_token } = tokenParts // extract from object
  const isSessionValid = validateSession(id_token) // check exp time etc and return true / false

  if (isSessionValid) {
    store('id_token', id_token)
    store('access_token', access_token)

    window.history.replaceState(null, null, window.location.pathname)
  }

我在我正在处理的代码库中看到了很多这种模式,用一个值调用一个方法,将该值赋给一个变量,将该变量传递给另一个方法并将结果赋值给另一个变量......等等直到你需要移动程序执行所需的值。

从我所看到的,功能应该是真的,做一件事 - 而不是那些难以测试的大规模,复杂的节拍。

我的问题是,在上面的伪代码的情况下,如何将其重构为返回另一个函数的结果的函数等等?

我想我需要像

这样的东西
const sessionisValid = validateSession(window.location)

validateSession = ({search, hash}) => (queryParams(search || hash))=> hasTokenExp({id_token})

但我不明白......

  1. 如果这是函数编程/组合应该如何工作
  2. 是最好的方法
  3. 如果我过于复杂的事情

1 个答案:

答案 0 :(得分:1)

  

使用值调用方法,将该值赋给变量,将该变量传递给另一个方法并将结果分配给另一个变量......依此类推,直到您需要移动程序执行所需的值为止。

这完全没问题。您正在构建来自多个小功能的大功能 - 正是您应该如何在功能编程中实现它。这些变量只是布线所必需的。

你所展示的是不是一个庞大而复杂的野兽,它是非常清晰和干净的代码。如果你愿意,可以很容易地自己测试所有的小功能。

因为所有这些函数都是纯粹的,并且你的变量是不可变的,所以很容易从

重构你的代码
const { search, hash } = window.location // get search / hash from url
const { id_token, access_token } = queryParams(search || hash)
const isSessionValid = validateSession(id_token) // check exp time etc

if (isSessionValid) {
    store('id_token', id_token)
    store('access_token', access_token)

    window.history.replaceState(null, null, window.location.pathname)
}

function getSession({search, hash}) {
    const { id_token, access_token } = queryParams(search || hash)
    return {
        id_token,
        access_token,
        isSessionValid: validateSession(id_token)
    };
}

const { id_token, access_token, isSessionValid } = getSession(window.location);
if (isSessionValid) {
    store('id_token', id_token)
    store('access_token', access_token)

    window.history.replaceState(null, null, window.location.pathname)
}

但除非您可以在多个地方使用getSession,或者您需要这个抽象层来进行代码组织,否则重构是不必要的。

  

如何使用函数组合进行重构?

它真的不可能。只有当一个函数的结果被输入另一个函数而不是其他函数时,函数组合才起作用。但在您的代码中,access_tokenid_token用于多个位置。虽然可以在pointfree style中表达这一点,但它复杂,缓慢且过于抽象。变量在这里更容易使用。

  

我在我正在处理的代码库中看到了很多这种模式

模式究竟是什么?每当您看到重复的代码时,您可能想要抽象出公共部分。但是您需要评估代码块中有多少公共部分和多少个不同的部分。虽然总是可行的,但通常不值得。