TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

RxJS is great. So why have I moved on?

82 点作者 swannodette超过 9 年前

12 条评论

disantlor超过 9 年前
Discovering and mastering bacon.js&#x2F;FRP completely changed the way I think about programming. It hugely increased the quality and stability of my code in ways that continue to surprise and amaze me. I cannot recommend it enough, but this article definitely has me curious about ClojureScript.<p>In the meantime, the biggest issue I&#x27;ve had with bacon is figuring out what are the best practices in organizing the code. One does end up with a lot of streams or variations&#x2F;combinations on streams used for different purposes. Eventually it does become hard to follow, as the author mentions, though because all state is self-contained you can change any one part with a high degree of confidence that it won&#x27;t break other features.<p>Still there must be some ideas out there that don&#x27;t involve incorporating a full blown framework&#x2F;SPA architecture. The author of bacon has a blog post on the subject but it seemed to me that there could be better ways still. Anyone have any suggestions?
评论 #10753555 未加载
评论 #10753451 未加载
评论 #10754279 未加载
评论 #10753614 未加载
评论 #10756507 未加载
Skywing超过 9 年前
The Clojure, and ClojureScript, hype train is effective. I&#x27;ve been interested in learning Clojure for several years. Every other week, or so, I&#x27;ll see a tweet or blog post that makes me want to drop JavaScript and move over to ClojureScript. The community looks like a great one to be part of, from an outsider&#x27;s perspective. With that said, I&#x27;ve never been able to break beyond that learning curve, or have that &quot;ah hah!&quot; moment. I&#x27;ve been able to learn a lot of different languages over the years, and I so want Clojure to be one of them but it just hasn&#x27;t happened for me, yet. This blog post puts my issue into words very well, it feels like I&#x27;m trying to program in mandarin and I struggle to be efficient at what seem like the most basic of tasks. A script that I could knock out in 20 minutes, with C# or JavaScript, will take me hours or days in Clojure because of the lack of muscle memory or something. My excitement always fades back into thoughts of &quot;meh is it really worth the effort&quot;, at which point I usually just revert back to JS. :(
pkese超过 9 年前
RxJS has a steep learning curve and is quite hard to really understand beyond basic examples that fit on a presentation slide. It might be a great tool for really smart developers, but I wouldn&#x27;t share any large RxJS code in a developer team where all developers are not at least 200% geniuses.<p>The whole thing reminds me of C++ years ago, where the language allowed for really smart and efficient coding style, but many less skilled developers at the time had problems with deep understanding of templates, operator overloading, multiple inheritance, various constructors and such. Pragmatic companies (e.g. Mozilla) thus decided to ban all the advanced features and stick just to basic ones so that the code would be maintainable.<p>I think RxJS is facing similar fate. I&#x27;ve spent quite some time learning it and I think it is one of the more complex paradigms on the market today. In addition there isn&#x27;t much useful documentation. Feel free to check stack overflow and find out about the struggles people are going through tying to extend basic examples (e.g. google for rxjs mousedrag).
programminggeek超过 9 年前
Building complex things is hard. Every tool breaks down when enough complexity is thrown at it.<p>The answer is to build less complex things.
davexunit超过 9 年前
I don&#x27;t fully understand the argument against FRP here. It seems like the author has passed on FRP in favor of coroutine-like asynchronous programming. I don&#x27;t view one as replacement for the other, but as different layers of an asynchronous programming system. Coroutines are great for async and imperative tasks, while FRP is great for async and functional tasks with persistent data. My own FRP implementation [0] in Guile Scheme is built <i>on top of</i> a coroutine implementation [1], which in turn is built on top of Guile&#x27;s first-class delimited continuations. [2]<p>That said, the author specifically talks about RxJs and Bacon.js, both of which have two major problems for me:<p>1) They don&#x27;t satisfy the closure property. They both have two fundamental data types: event streams and properties. Certain combinators expect streams, and others expect properties. Compare this with API&#x27;s like Elm&#x27;s which just have a single type: the signal. The closure property is satisfied here and programming is much more pleasant.<p>2) They both deal with stream&#x2F;property life cycles. Objects need to explicitly unsubscribe from other objects, and streams may have a beginning and an end (i.e. they may be marked as having no value or marked as being done producing values). I think this is a mistake that complicates the API. FRP objects should <i>always</i> have a value, have no notion of being done, and not require the equivalent of manual memory management to clean up. My Scheme implementation uses weak references to automatically unsubscribe signals when they are no longer referenced, which is basically only during development when changing things at the REPL. Bacon and RxJS can&#x27;t do something like this because (and correct me if I&#x27;m wrong), no JS standard prior to ES6 has weak data structures. Anyway, after all the hacking, the final program has a static signal graph, just like Elm, which I think is the right way to do things.<p>[0] <a href="https:&#x2F;&#x2F;git.dthompson.us&#x2F;sly.git&#x2F;blob&#x2F;HEAD:&#x2F;sly&#x2F;signal.scm" rel="nofollow">https:&#x2F;&#x2F;git.dthompson.us&#x2F;sly.git&#x2F;blob&#x2F;HEAD:&#x2F;sly&#x2F;signal.scm</a><p>[1] <a href="https:&#x2F;&#x2F;git.dthompson.us&#x2F;sly.git&#x2F;blob&#x2F;HEAD:&#x2F;sly&#x2F;coroutine.scm" rel="nofollow">https:&#x2F;&#x2F;git.dthompson.us&#x2F;sly.git&#x2F;blob&#x2F;HEAD:&#x2F;sly&#x2F;coroutine.sc...</a><p>[2] <a href="https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;guile&#x2F;manual&#x2F;html_node&#x2F;Prompts.html" rel="nofollow">https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;guile&#x2F;manual&#x2F;html_node&#x2F;Prompts....</a>
评论 #10754447 未加载
bad_user超过 9 年前
Core.async is not a substitute for Rx.<p>As a disclaimer I&#x27;m the author of an Rx-inspired library for Scala [1] and that also works for Scala.js in the browser. Shameless plug aside, Scala also has Future&#x2F;Promise in its standard library and now due to macros support it got scala&#x2F;async [2], a library that gives you the &quot;await&quot; keyword in Scala, so in Scala you also get this kind of M:N multithreading that looks like synchronous code. This in addition to Akka and other possibilities.<p>In other words I&#x27;ve worked with both approaches and Core.async is not comparable with Rx. I do understand the author&#x27;s woes, as sometimes the Rx model is misapplied, plus it&#x27;s hard to understand for the unfamiliar.<p>One of my colleagues was complaining once that &quot;<i>but I don&#x27;t know what the debounce operator does and it&#x27;s hard for me to read that</i>&quot;. And I told him: <i>yeah dude, but try implementing the logic in debounce by yourself and see how readable that is</i>.<p>And that&#x27;s exactly why Rx is problematic. On one hand because stream processing is fundamentally hard, no matter what model you choose. And on the other hand Rx comes with a lot of useful operators that do a lot for you, but then you have to learn about them.<p>For the naysayers, I&#x27;ll just leave this piece of code with a challenge for implementing it with core.async and compare in terms of readability and note this is a copy paste from actual production code ...<p><pre><code> commands .groupBy(w =&gt; (w.assetID, w.commandID)) .mergeMap { gr =&gt; gr.timeout(30.seconds, Observable.empty) .throttleLast(1.second) .distinctUntilChanged .echoRepeated(5.seconds) .whileBusyBuffer(DropOld(30)) } </code></pre> What it does is to split the signals for each asset and command, for each of these it&#x27;s supposed to sample the signal by 1 second, but in case the same value is repeated over and over again or in case the channel goes silent, then the last value will end up signaled every 5 seconds (reducing the traffic to our OpenTSDB). Finally for each key we close the stream after 30 seconds of inactivity. And then for each such key it does buffering of at most 30 elements and in case the consumers are too slow, then these buffers start dropping older elements on overflow. And then we merge everything back.<p>I would also show you how we are modeling state machines with the &quot;scan&quot; operator, state machines that are evolved from signals coming from multiple sources, but the sample would be too long. In any case &quot;scan&quot; allows you to use pure functions and data-structures, so you can test your business logic without interactions to third party services, mocks, stubs or whatever.<p>I have to deal with such code all the time. And I&#x27;ve seen such code implemented in a classic fashion as well. You basically end up with Maps storing stuff and with ifs and whiles and with manual timers in an unholy dance of mutation so hard to understand and debug that it would make grown men cry.<p>But then such solutions are not silver bullets. Rx, CSP, futures, actors are not silver bullets to be applied everywhere, with all of them having a sweet spot for which they excel. I&#x27;m actually using Rx, actors, futures, scala&#x2F;sync in the same project and it&#x27;s great.<p>Also, one last note: Rx is not FRP ;-)<p>[1] <a href="https:&#x2F;&#x2F;github.com&#x2F;alexandru&#x2F;monifu&#x2F;" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;alexandru&#x2F;monifu&#x2F;</a><p>[2] <a href="https:&#x2F;&#x2F;github.com&#x2F;scala&#x2F;async" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;scala&#x2F;async</a>
评论 #10754555 未加载
评论 #10756311 未加载
评论 #10757631 未加载
评论 #10753897 未加载
theknarf超过 9 年前
If you feel that RxJS is a bit hard, but don&#x27;t want to go all crazy and switch to ClojureScript; then Redux is pretty good. It&#x27;s not as &quot;powerfull&quot; as RxJS and it has some guidelines on how you should structure code. It also have very good tooling integrations, and debug-ability.
yrns超过 9 年前
Once I found flyd [0] I never looked back at any of the other streams libraries. It&#x27;s very simple, easy to jump into, and doesn&#x27;t have the stream&#x2F;property split. There&#x27;s not a lot of code, so it doesn&#x27;t make debugging any harder.<p>Also, there is js-csp [1] if you want to use CSP without having to make the jump to ClojureScript. Works great.<p>[0] <a href="https:&#x2F;&#x2F;github.com&#x2F;paldepind&#x2F;flyd" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;paldepind&#x2F;flyd</a> [1] <a href="https:&#x2F;&#x2F;github.com&#x2F;ubolonton&#x2F;js-csp" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ubolonton&#x2F;js-csp</a>
zackangelo超过 9 年前
The article mentions that async&#x2F;await functionality hasn&#x27;t landed in Javascript yet. I wonder if you can get the same functionality today using scala.js [0] and the scala&#x2F;async [1] library.<p>I believe it should work. The scala&#x2F;async library is just a set of macros that transform blocks of code using async&#x2F;await into for comprehensions.<p>[0] <a href="http:&#x2F;&#x2F;www.scala-js.org" rel="nofollow">http:&#x2F;&#x2F;www.scala-js.org</a> [1] <a href="https:&#x2F;&#x2F;github.com&#x2F;scala&#x2F;async" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;scala&#x2F;async</a>
评论 #10756499 未加载
评论 #10764029 未加载
Keats超过 9 年前
What do you think of something like <a href="http:&#x2F;&#x2F;mweststrate.github.io&#x2F;mobservable&#x2F;" rel="nofollow">http:&#x2F;&#x2F;mweststrate.github.io&#x2F;mobservable&#x2F;</a> ?
评论 #10753044 未加载
Matthias247超过 9 年前
My personal experience was that there is not a one-thing-fits-all solution. There are things that can be beautifully implemented with Rx, and there are other things were I found that using Promises (probably in combination with async&#x2F;await) makes things clearer. My current project (which involes quite a bit of Typescript code) uses everything from Rx, Promises up to plain old node EventEmitters and streams, and I&#x27;m actually really happy with all of it.
thesorrow超过 9 年前
RxJS is not designed to be pull-based which makes it hard to use it for something else than UI code. I hope this will change with RxNext.
评论 #10757868 未加载