You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
const getRedirectToParam = (parsedQuery) => parsedQuery.redirect_to;
// we have to re-write this a bit to return a result.
const storeRedirectToQuery = (redirectTo) => {
localStorage.setItem("REDIRECT_TO", redirectTo)
return redirectTo;
};
function persistRedirectToParam() {
const decoded = storeRedirectToQuery(
decodeURIComponent(
getRedirectToParam(
qs.parse(window.location.search)
)
)
)
return decoded;
}
constpipe=require("lodash/fp/pipe");constqs=require("qs");constgetRedirectToParam=parsedQuery=>parsedQuery.redirect_to;conststoreRedirectToQuery=redirectTo=>{localStorage.setItem("REDIRECT_TO",redirectTo);returnredirectTo;};constpersistRedirectToParam=fp.pipe(tryCatch({tryer: qs.parse,catcher: ()=>{return{redirect_to: null// we should always give back a consistent result to the subsequent function};}}),getRedirectToParam,decodeURIComponent,tryCatch({tryer: storeRedirectToQuery,catcher: ()=>null// if localstorage fails, we get null back}));// to invoke, persistRedirectToParam(window.location.search);
constpipe=require("lodash/fp/pipe");constqs=require("qs");constgetRedirectToParam=parsedQuery=>parsedQuery.redirect_to;conststoreRedirectToQuery=redirectTo=>{localStorage.setItem("REDIRECT_TO",redirectTo);returnredirectTo;};constsafeParse=tryCatch({tryer: qs.parse,catcher: ()=>{return{redirect_to: null// we should always give back a consistent result to the subsequent function};}});constsafeStore=tryCatch({tryer: storeRedirectToQuery,catcher: ()=>null// if localstorage fails, we get null back});constpersistRedirectToParam=fp.pipe(safeParse,getRedirectToParam,decodeURIComponent,safeStore);
[译] 编写函数式的 JavaScript 实用指南
函数式编程很棒。随着 React 的引入,越来越多的 JavaScript 前端代码正在考虑 FP 原则。但是我们如何在我们编写的日常代码中开始使用 FP 思维模式?我将尝试使用日常代码块并逐步重构它。
我们的问题:用户来到我们的登录页面链接后会带一个
redirect_to
参数。就像/login?redirect_to =%2Fmy-page
。请注意,当%2Fmy-page
被编码为URL
的一部分时,它实际上是/ my-page
。我们需要提取此参数,并将其存储在本地存储中,以便在完成登录后,可以将用户重定向到my-page
页面。第 0 步:必要的方法
如果我们以最简单方式来呈现这个解决方案,我们将如何编写它?我们需要如下几个步骤
我们还必须将
不安全
的函数放到try catch
块中。有了这些,我们的代码将如下所示:第 1 步:将每一步写为函数
暂时,让我们忘记
try catch
块并尝试将所有内容表达为函数。当我们开始将所有“结果”用函数的方式表示时,我们会看到我们可以从主函数体中重构的内容。这样处理后,我们的函数变得更容易理解,并且更容易测试。
早些时候,我们将测试主要函数作为一个整体。但是现在,我们有 4 个较小的函数,其中一些只是代理其他函数,因此需要测试的足迹要小得多。
让我们识别这些代理函数,并删除代理,这样我们就可以减少一些代码。
第 2 步 尝试编写函数式
好的。现在,似乎
persistRedirectToParam
函数是 4 个其他函数的“组合”让我们看看我们是否可以将此函数编写为合成,从而消除我们存储为const
的中间结果。这很好。但是我同情读取这个嵌套函数调用的人。如果有办法解开这个混乱,那就太棒了。
第 3 步 更具可读性的组合
如果你已经完成了以上的一些重构,那么你就会遇到
compose
。Compose
是一个实用函数,它接受多个函数,并返回一个逐个调用底层函数的函数。还有其他很好的资源来学习composition
,所以我不会在这里详细介绍。使用
compose
,我们的代码将如下所示:compose 内的函数执行顺序为从右向左,即最右边的函数(最后一个参数)最先执行,执行完的结果作为参数传递给前一个函数。因此,在 compose 链中调用的第一个函数是最后一个函数。
如果你是一名数学家并且熟悉这个概念,这对你来说不是一个问题,所以你自然会从右到左阅读。但对于熟悉命令式代码的其他人来说,我们想从左到右阅读。
第 4 步 pipe(管道)和扁平化
幸运的是这里有
pipe(管道)
和compose
做了同样的事情,但是执行顺序和compose
是相反的,因此链中的第一个函数最先执行,执行完的结果作为参数传递给下一个函数。而且,似乎我们的
persistRedirectToParams
函数已经成为另一个我们称之为op
的函数的包装器。换句话说,它所做的只是执行op
。我们可以摆脱包装并“扁平化”我们的函数。差不多了。请记住,我们适当地将 try-catch 块留在后面,以使其达到正确的状态?好的接下来,我们需要一些方式来介绍它。qs.parse 和 storeRedirectToQuery 都是不安全。一种选择是使它们成为包装函数并将它们放在 try-catch 块中。另一种
函数式方式
是将try-catch
表示为一种函数。第 5 步 作为函数的异常处理
有一些实用程序做到了这一点,但让我们自己尝试写一些东西。
我们的函数在这里需要一个包含 tryer 和 catcher 函数的 opts 对象。它将返回一个函数,当使用参数调用时,使用所述参数调用 tryer 并在失败时调用 catcher。现在,当我们有不安全的操作时,我们可以将它们放入 tryer 部分,如果它们失败,则从捕获器部分进行救援并提供安全结果(甚至记录错误)。
第 6 步 把所有东西放在一起
因此,考虑到这一点,我们的最终代码如下:
这或多或少是我们想要的。但是为了确保代码的可读性和可测试性得到改善,我们也可以将“安全”函数(tryCatch 函数)分解出来。
现在,我们得到的是一个更强大功能的函数,由 4 个独立的函数组成,这些函数具有高度内聚性,松散耦合,可以独立测试,可以独立重用,考虑异常场景,并且具有高度声明性。
有一些 FP 语法糖使这变得更好,但是这是以后的某一天。
The text was updated successfully, but these errors were encountered: