React hooks在框架编程上具有明【版权所有】唐霜 www.tangshuang.net【本文受版权保护】显特征,在推广functional组件的【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。进程中,javascript是天然具有函【作者:唐霜】【原创内容,转载请注明出处】数式编程优势的语言,因此,react团队【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】越来越倾向并重视hooks的应用。hoo【原创不易,请尊重版权】【原创不易,请尊重版权】ks编程之所以拥有比较大的魅力,除了它抹【转载请注明来源】原创内容,盗版必究。平class组件和functional组著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。件在生命周期上的差异之外,更重要的是,它【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】让react开发者践行代数效应。Reac【原创不易,请尊重版权】【未经授权禁止转载】t核心团队成员Sebastian Mar未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。kbåge(React Hooks的发明者)曾说:著作权归作者所有,禁止商业用途转载。
本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。原创内容,盗版必究。我们在React中做的就是践行代数效应(【原创不易,请尊重版权】【版权所有,侵权必究】Algebraic Effects)。
【关注微信公众号:wwwtangshuangnet】【本文受版权保护】著作权归作者所有,禁止商业用途转载。
本文就将从践行代数效应的角度出发,探索我【转载请注明来源】著作权归作者所有,禁止商业用途转载。们在其他场景(非react functi【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。onal组件)下践行代数效应的可能性。
【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。什么是代数效应?著作权归作者所有,禁止商业用途转载。
【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】在理解什么是“代数效应”之前,请先阅读一转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】下这篇本文版权归作者所有,未经授权不得转载。文章。为了理解“代数”,我们举一个例子:
【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】已知: y + 2x = 9 (1) 2y + x = 15 (2) 求: x + y = ? -------------------------- 由 (1) 可得: y = 9 - 2x (3) 将 (3) 代入 (2) 可得: 2(9 - 2x) + x = 15 => 18 - 3x = 15 => x = 1 (4) 将 (4) 代入 (3) 可得: y = 7 将求得的x, y代入x + y可得 x + y = 8
这就是代数,本质上,代数是研究函数(数的著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net关系)的科学,它的精髓在于“代入”这个动【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。作,它的主要方法是解方程。
原创内容,盗版必究。转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net想象一下,上面的题,如何用程序来解决呢?原创内容,盗版必究。【本文首发于唐霜的博客】不,我的意思是,你所写的程序,如何解出 【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net3x2【访问 www.tangshuang.net 获取更多精彩内容】 + y【转载请注明来源】2【版权所有,侵权必究】 = ? 甚至更多的算式?这和我们往常的【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net编程思路恰恰相反,我们以往的编程思路,是转载请注明出处:www.tangshuang.net【未经授权禁止转载】通过不同点测算出函数,再根据函数获得另一转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net个点,这是机器学习的基本思路。但是,我们本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net的编程,尚未有以代数为基本的思路。
原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】
常见的编程思路,已知A、B,求C点原创内容,盗版必究。
【版权所有,侵权必究】原创内容,盗版必究。未经授权,禁止复制转载。【版权所有,侵权必究】
代数要解决的问题,已知A在1、2函数上,【作者:唐霜】【版权所有】唐霜 www.tangshuang.net求函数3的方程
【转载请注明来源】本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。在第2个图中,已知的是1、2两个函数都通【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net过A点,但A点具体值我们并不知道,要求出【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。的,是任何可能穿过A的其他函数的方程。
【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。JS原生代数效应【本文首发于唐霜的博客】
【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】【原创不易,请尊重版权】在本节开头引用的那篇文章里提到了,总结而【原创内容,转载请注明出处】【未经授权禁止转载】言,代数效应,是让编程(代码)可以自上而下书本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。写,但让程序的执行可以在不同函数间跳跃的【未经授权禁止转载】【作者:唐霜】编程效果。代数效应对我们编程有什么启示呢?实际上原创内容,盗版必究。【本文首发于唐霜的博客】,在js里面已经有这样的编程方式:
【本文受版权保护】著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】【未经授权禁止转载】async function doSome() {
const v1 = do1()
const v2 = await do2(v1)
const v3 = do3(v2)
const v4 = await do4(v3)
return v4
}
或者:著作权归作者所有,禁止商业用途转载。
【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】转载请注明出处:www.tangshuang.netfunction* doSome() {
const v1 = do1()
const v2 = yield do2(v1)
const v3 = do3(v2)
const v4 = yield do4(v3)
return v4
}
以及for await…of著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。语法,都是具有代数效应的编程方式。简单说【本文受版权保护】【未经授权禁止转载】,js中的代数效应表达方式,让我们通过a本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。wait和yield语法,让程序从原有的【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】函数执行流中,跳到另外一个执行流中完成副【本文受版权保护】【版权所有】唐霜 www.tangshuang.net作用,并将副作用结果返回给当前执行流,再【未经授权禁止转载】未经授权,禁止复制转载。用这个结果进行剩下的计算。所以说,上面说【转载请注明来源】【转载请注明来源】的“函数间跳跃”的主要目的,是将函数式和【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】副作用进行分离,保持函数式编程的同时,又【版权所有,侵权必究】转载请注明出处:www.tangshuang.net支持副作用操作。
本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】但是,async/await和gener本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。ator函数具有传染性,它们要求所有外部【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。编程在语法上必须采用不可替代的表示式,从【本文受版权保护】【本文受版权保护】而让代数效应的实现不具备普适性和通用性。
本文作者:唐霜,转载请注明出处。【转载请注明来源】本文作者:唐霜,转载请注明出处。模拟代数效应的实现【原创不易,请尊重版权】
【未经授权禁止转载】原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。在js领域,不止一人提出了新的语法以支持【版权所有,侵权必究】【版权所有,侵权必究】这种编程方法。比较典型的编程方法如下:
【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】try {
const v1 = do1()
const v2 = raise '1'
const v3 = do3(v2)
const v4 = raise '3'
return v4
}
handle (e) {
if (e === '1') {
resume 'v2'
}
else if (e === '3') {
resume 'v4'
}
}
关键字都用红色标注出来了。它和 try&【版权所有,侵权必究】【未经授权禁止转载】#8230;catch 一样,通过 th【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。row 抛出异常,通过 catch 捕获【版权所有,侵权必究】【原创不易,请尊重版权】异常一样,在这段代码中,通过 raise【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。 抛出代数陷阱,通过 handle 捕获转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】陷阱,在捕获块中应对(处理)陷阱,通过 【本文受版权保护】转载请注明出处:www.tangshuang.netresume 跳出陷阱,将处理结果带出陷未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。阱作为值继续执行 try 块中的剩余代码【版权所有,侵权必究】【本文受版权保护】。它和 try…catch的转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。区别仅仅在于try…catc【版权所有】唐霜 www.tangshuang.net【转载请注明来源】h一旦throw,后续代码就不会再执行。【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】而try…handle不仅可转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】以持续执行至代码块结束,而且由于resu本文作者:唐霜,转载请注明出处。原创内容,盗版必究。me的使用可以是随意的,所以在handl【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】e中可以写异步操作,从而在无await/著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netyeild的情况下,让异步操作变得更加像著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】同步操作。
原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】除了在形式上的新颖有趣,更重要的是实用性【本文受版权保护】【版权所有】唐霜 www.tangshuang.net。
本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】【作者:唐霜】本文作者:唐霜,转载请注明出处。在以前,我们要为一个函数提供某种修改的能【转载请注明来源】本文版权归作者所有,未经授权不得转载。力,我们也会尝试类似的方法,例如:
【未经授权禁止转载】【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netfunction calcZ() {
const x = calcX()
const y = calcY()
const z = x + y
return z
}
我们有这样一个函数,我们将这个函数提供给【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。其他人,他就可以用它来计算z的值。对于使转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】用它的人而言,需要提供calcX和cal【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】cY函数,这样,他就可以自定义x和y的计本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】算逻辑。这在简单全局场景是可以的,但在模【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net块化的今天,则不可行,除非要求写全局的c【未经授权禁止转载】【本文首发于唐霜的博客】alcX和calcY函数。
【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。但通过try…handle则【作者:唐霜】【未经授权禁止转载】让这个自定义x和y的计算逻辑变得简单:
【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.netfunction calcZ() {
const x = raise 'x'
const y = raise 'y'
const z = x + y
return z
}
对于使用者而言:未经授权,禁止复制转载。
原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。try {
const z = calcZ()
}
handle (e) {
switch (e) {
case 'x': {
resume 10
break
}
case 'y': {
resume 15
break
}
}
}
甚至,在handle中进行异步操作:未经授权,禁止复制转载。
【本文首发于唐霜的博客】【未经授权禁止转载】【原创内容,转载请注明出处】【本文受版权保护】【作者:唐霜】try {
const z = calcZ()
}
handle (e) {
switch (e) {
case 'x': {
setTimeout(() => {
resume 10
}, 1000)
break
}
case 'y': {
resume 15
break
}
}
}
这样,对于原始函数calcZ而言,它完全【版权所有,侵权必究】原创内容,盗版必究。是同步的,但我们却可以异步的获取x的值,本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。在异步求x值后,代入原来的函数中继续执行【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】后续计算。
【本文首发于唐霜的博客】【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】Hooks中的代数效应【原创内容,转载请注明出处】
【原创内容,转载请注明出处】【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。既然hooks的发明者Sebastian【作者:唐霜】【关注微信公众号:wwwtangshuangnet】 Markbåge说hooks在践行代数未经授权,禁止复制转载。【原创不易,请尊重版权】效应,那么我们是否需要换一种思维,去理解【原创内容,转载请注明出处】【原创不易,请尊重版权】hooks的运行原理。
原创内容,盗版必究。【本文首发于唐霜的博客】【未经授权禁止转载】function App() {
const [num, updateNum] = useState(0)
return (
<button onClick={() => updateNum(num => num + 1)}>{num}</button>
)
}
我们将上面这段代码进行翻译:【版权所有,侵权必究】
【本文受版权保护】著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.netfunction App() {
const num = raise 'state_num'
return <button>{num}</button>
}
我们去掉干扰信息,得到上面这段简单代码,本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】而hooks帮我们在react库内部完成著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net了如下工作:
原创内容,盗版必究。未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。function render() {
let state_num // 建立了一个变量用于缓存
try {
return App()
}
handle (e) {
if (e === 'state_num') {
return typeof state_num === 'undefined' ? 0 : state_num
}
}
}
这就是hooks在践行的代数效应。将上面【本文受版权保护】【版权所有】唐霜 www.tangshuang.net的代码进行扩展,我们可以非常方便的再写出未经授权,禁止复制转载。【转载请注明来源】updateNum的实现方式。
本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。当然,除了hooks,Suspense还著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】有Reconciler,都是对代数效应的【原创内容,转载请注明出处】【本文首发于唐霜的博客】践行,它们本质上就如我前文所说,在正常的【作者:唐霜】原创内容,盗版必究。程序流程中,允许我们停下来,去做另外一件【本文首发于唐霜的博客】原创内容,盗版必究。事,做完之后,我们可以再从被打断的地方继【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net续往下执行,而另外的那件事,可以是同步的未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】,也可以是异步的,理论上,它的执行过程与转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。我们当前的流程无关,我们仅关心(或根本不本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】关心)它的结果。
【本文受版权保护】【未经授权禁止转载】【版权所有,侵权必究】类hooks编程【作者:唐霜】
未经授权,禁止复制转载。【未经授权禁止转载】【作者:唐霜】【作者:唐霜】【本文首发于唐霜的博客】React hooks在实践代数效应,我【版权所有,侵权必究】【原创内容,转载请注明出处】们能否在其他环境下(非react相关)也【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。仿造hooks的思想,践行代数效应?问题的关键点在于,js并没有try【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。230;handle语法!
本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】【本文首发于唐霜的博客】我希望创建一种类hooks的编程。例如:
【本文受版权保护】【版权所有】唐霜 www.tangshuang.net【本文受版权保护】本文作者:唐霜,转载请注明出处。function calc() {
const x = get('x')
const y = get('y')
return x + y
}
如何实现呢?我们可以再提供一个接口,让开【作者:唐霜】本文作者:唐霜,转载请注明出处。发者规定get(‘xR【本文受版权保护】转载请注明出处:www.tangshuang.net17;)要做什么事情:
【转载请注明来源】【本文受版权保护】【作者:唐霜】【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。define('x', function(set) {
setTimeout(() => {
set(100)
}, 1000)
})
看,当执行get(‘x【本文首发于唐霜的博客】【版权所有,侵权必究】217;)时,define的第二个参数会【原创内容,转载请注明出处】【原创不易,请尊重版权】被执行,这个参数,就是try…本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。;handle中的handle部分。但是【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。,calc是同步的,而获取x的过程是异步本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。的,怎么办呢?再计算一次!本文作者:唐霜,转载请注明出处。
【本文受版权保护】【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net【本文受版权保护】著作权归作者所有,禁止商业用途转载。setup(function() {
const z = calc()
})
当set(100)被执行时,setup内本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。的函数再次执行,这样,z就可以被再计算一未经授权,禁止复制转载。【作者:唐霜】次,而此时get(‘x转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。217;)的结果为100。
【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net【本文受版权保护】结语【原创不易,请尊重版权】
【转载请注明来源】【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。未经授权,禁止复制转载。我最近写了一个新的小项目转载请注明出处:www.tangshuang.netAlgeb【原创内容,转载请注明出处】,我试图用代数效应的方式,去推翻我之前写原创内容,盗版必究。未经授权,禁止复制转载。databaxe这个库时的思想。我在这篇文章【关注微信公众号:wwwtangshuangnet】中提出了服务层的构想,但没有给出实现。我【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。在新库中,仍然延续“数据源”这个概念,同本文版权归作者所有,未经授权不得转载。【转载请注明来源】时也引入hooks的思想,对于数据源而言【转载请注明来源】【本文受版权保护】,它是固定的,它将从api接口获得某一个【原创内容,转载请注明出处】【版权所有,侵权必究】源的具体数据,但是,在使用时,却可以是同【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】步的写法(类hooks),通过“再计算一【本文受版权保护】原创内容,盗版必究。次”的方式,让数据的下游(视图层)对数据本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】的变化进行响应。当然,这还只是一次尝试。未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】我看到有人提出了了try…hand本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netle的议案,或许未来不久,我们就可以在es中原生支【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net持这种方案了。
本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。原创内容,盗版必究。


这个文章写的最容易懂了