你好!
在本文中,我正在定义练习,对您挑战,并给予我自己的答案。
我会详细解释我的思维和小警报,我们将使用不经常使用的操作员!
是时候关闭您的命令性编程思维并打开反应性的。这将是一个有趣的旅程。
介绍
如果您在我的时候一直在关注我,那么您现在可能知道我是RXJS的忠实粉丝。 ,如果您还没有关注我,那是一个非常好时机放松一下,然后单击“关注”按钮,然后我们开始融化大脑𧧥!
到目前为止,我已经写了3篇文章,这些文章大量使用或完全专用于RXJS:
Brute-forcing an encrypted message from Enigma using the web worker API | Building a reactive microwave for Ryan Cavanaugh with RxJs | RxJS: Avoid an easy mistake when using startWith |
这是迄今为止最具挑战性的。
最近,我们在工作中购买了Split flap display,也称为“ Solari Board”或“ Solari出发委员会”。
我们得到的一个已连接到一个,我们可以从应用程序设置文本,然后更新IRL。显示各种重要的消息或统计信息很有趣。
我敢肯定,当所有字母都在旋转时,您知道它会令人着迷,并且它们突然间都停止,一个接一个地显示最后一句话。使用RXJS构建我们的挑战不是一个很酷的挑战吗?
挑战规则
在开始之前,让我们定义预期的结果:
- 反应性,反应性,反应性。没有命令的编程。一切都应通过流来管理,而不是依靠外部状态。当然,例如,将允许的字母定义为一个常数是可以的。但是,应用程序的所有内部状态都应自我包含在流中
- 显示在显示上的20个字母(无论如何易于更改)
- 可以显示从
A
到Z
的所有字母,可以在字母/单词之间具有空格,而从0
到9
- 每当更新一个字母时,页面应输出董事会的新状态
- 如果文本在任何时间点发生变化,无论是否正在进行中,或者是否已停止,则不应从头开始。就像实际上一样,它应该从目前的位置继续前进,然后将字母滚动到新位置
预期输出的示例:
挑战你!
是的!我认为,如果阅读这篇文章的人是独自一人并分享他们走了多远会很有趣。
为了使它变得更容易并且不介绍痛苦的设置,我创建了一个 Stackblitz template 准备出发!
它包含utils.ts
中的一些实用程序来操纵字母和DOM,因此我们仍然专注于流。
如果您决定试一试,请分配原始的Stackblitz或如果您愿意的话,请从头开始。可以随意修改我制作的模板中的任何内容。它只是在这里作为帮助的基础,而不是在这里阻止您。
不要忘记保存您的stackblitz并将其作为评论。即使您没有一路走。让我们讨论结果!
我的解决方案
在编程中,可能有多个解决方案可以实现相同的结果。因此请记住,这是我自己的方法,有人可以提出一个不同甚至更好的解决方案。
从现在开始,请注意,如果您想首先使用自己的解决方案工作,那么以下意愿是一个可能的答案,所以这确实是一个很大的扰流板。
不进一步的ADO,让我们直接跳进去。
<<当我必须构建一个依赖可观察到的功能时,我尝试做的第一件事是我脑海中的图片如何相互作用。露天流,内流。虽然可能很难在视觉上表示,但我将自己想构建的内容可视化为marble diagrams和所有连接的管道的混合物。我会尽力说明这一点,但要忍受我,因为这并非易事。
这与我可以以视觉方式运作的方式一样近。现在让我们挖掘代码。
提醒您,我不会潜入我为管理字母和DOM操作的Utils文件中。随时查看here以进行整个实施。
现在,如果我们专注于流本身并暂时放弃DOM的更新,这是我们代码的核心:
在我们研究细节之前,让我们考虑一下RXJS的美和力量。
请记住,上面的 14行代码能够像拆分板板一样显示字符串,并带有动画(在每个字母上分别应用延迟),保持当前状态,如果文本更改,请开始将字母从我们的位置完全更改为新位置。如果我们尝试应用文本并将其更改为另一个,则它还可以正确管理,而第一个仍在运行时,而无需从头开始重置并准确地捡起它的位置。 rxjs确实是美女。
我们使用的第一件事是输入。这是一个简单的Subject
,我们可以随时随地next
进入。例如,这可以绑定到输入文本。
然后,我们将该字符串映射到与板字母匹配的输入。意思是,我们希望它成为一系列炭。我们显示的每个条目的一个字符。例如,假设董事会支持10个字符显示为简单起见,如果我们通过'HELLO'
,我们会返回['H', 'E', 'L', 'L', 'O', '', '', '', '', '']
。
然后ð¥...我们使用koude9,这是我第一次找到它的用例ð。顾名思义,它是switch
和scan
的混合物:
-
switch
意味着如果父溪再次发出时,如果它仍在运行 ,我们将停止该流。
-
scan
就像reduce
。这意味着它将累加器,当前值和您从中返回的值成为新的蓄能器。除了使用reduce
的情况下,它将等待流在发射之前完成,并使用scan
发出所有中间结果。在这里,switchScan
意味着我们的内部流将被订阅,它将能够做出多个排放,以成为新的累加器,如果父级流再次发出(我们的input$$
主题),我们停止更改字母,然后再次更改以达到刚刚提供的新字符串。在这里,该运营商做得很棒,它是能够在其中间停止动画并继续董事会目前不重置的地方的关键
然后我们有一个combineLatest
。在我在上方绘制的图中,combineLatest
在这里组装所有流的流(每字母1) 表示为垂直绿色箭头。
构建传递给combineLatest
的流数组,我们循环循环到刚收到的当前字母,每个人都会计算我们当前拥有的内容与该瓷砖的目标字母之间的所有字母。然后,我们发出了我们需要使用from
的每个中间字母。
最后,随着from
发射所有中间字母,我们将concatMap
与delay
一起使用,以确保我们以相同的顺序排放中间字母,并且每个人之间的延迟以模拟动画。
这是final version live in Stackblitz:
结论
这是一个 lot ,但是很有趣。不是吗?
每当我有机会像这样编写RXJS代码时,它确实使我想起了为什么我喜欢编码。当我大约6年前发现有关反应性编程时,它确实震惊了我的想法,我想和它一起玩,直到我足够舒适地表达自己,就像大多数开发人员一样,像大多数开发人员一样,表达了我们的命令式代码倾向于先学习。现在能够写这篇文章让我真的很高兴,我尽可能分享对反应性编程的热情。
rxjs是一种强大的工具,需要时间来学习。但是,一旦您设法将头缠绕在它上,就可以以相对简单或至少可读的方式处理真正复杂的用例。
我希望您喜欢这篇文章,如果您确实让我知道并最终发表评论。很高兴听到花时间阅读帖子ð的人的回音!如果您自己参加挑战,请分享指向您的Stackblitz的链接,或者让我们知道您走了多远!
如果您对有关角度,RXJ,开源,自托管,数据隐私的更多文章感兴趣,请随时按下关注按钮以获取更多信息。感谢您的阅读!
找到错字了?
如果您找到了一个错别字,可以改进的句子或该博客文章中应更新的其他内容,则可以通过GIT存储库访问并提出拉请请求。不要发表评论,而是直接转到https://github.com/maxime1992/my-dev.to,并通过更改打开新的拉请请求。如果您感兴趣我如何通过git and ci管理dev.to。