6 ms·
Taming the Asynchronous Beast with CSP in JavaScript
- craigching 12y agoHe mentions using CSP with JavaScript: > It's safe to say that it's becoming quite popular (and validated) and I think we need to try it out in JavaScript. To be clear, and he mentions that Clojure has core.async, it's been done in JavaScript (if you will) already via ClojureScript. David Nolen has done a series of posts on it starting at [1]. [1] -- http://swannodette.github.io/2013/07/12/communicating-sequential-processes/ http://swannodette.github.io/2013/07/12/communicating-sequen... EDIT: And I should have finished reading the post before posting this. He does mention David Nolen's series of posts on ClojureScript and core.async
- BrianEatWorld 12y agoMy understanding of Javascript is that it is essentially single-threaded. Maybe I am mistaken, but if that is indeed the case, how does something like JS-CSP or Clojurescript's core.async accomplish concurrency? Has there been a change in the underlying Javascript? Is it just using tricks to make single-thread act like multi-thread?
- arnarbi 12y agoShort answer: Yes. Concurrency does not necessarily mean parallelism (multi-threading). CSP-derived mechanisms provide abstractions for units-of-work to yield control to other units-of-work. Here, a unit of work is a function invocation, but it can be a block, a thread-like object etc. With such primitives it is fairly easy to build cooperative (as opposed to pre-emptive) concurrency mechanisms. For a mature example, see e.g. http://www.stackless.com/ http://www.stackless.com/
- craigching 12y agoIn the JavaScript "user space" you don't have access to threads (with the exception of web workers), but the JS engines themselves are multi-threaded and fully concurrent. This is why your UI doesn't freeze when doing XHR (assuming you're not doing synchronous XHR) and represents the need for elegantly handling asynchronicity.
- dminor 12y agoSay you have: function one() { console.log("one"); setTimeout(one, 1000); } function two() { console.log("two"); setTimeout(two, 2000); } one(); two(); They are executing concurrently, but never in parallel (since javascript is single threaded). Now, how do you coordinate them if you need to? This is what CSP helps you do.
- lbradstreet 12y agoI've spent a fair amount of time in core.async, and I feel like I'm on the edge of enlightenment here, but I don't quite understand how CSP helps with this example. Is the point that you can take multiple puts off the channel in one go? That's the only thing I can think of. Maybe you could present the CSP alternative, and a basic example use case? * edit: I guess a basic example is a sliding-buffer that only keeps, and thus only reacts to, the last mouse event. Is this on the right track?
- dminor 12y agoThe example was more about showing that concurrency and threads are not synonymous, but you can imagine one of the functions producing a stream of values and the other waiting for and consuming them. In vanilla javascript, you have to resort to breaking your code up into callbacks, which looks trivial in a two function example but becomes unwieldy once you add a few layers and do error handling. With CSP you organize your code around channels according to the code's logic, rather than according to the needs of coordination. This makes things like error handling and reasoning about your logic much simpler.
- lbradstreet 12y agoI totally agree that it helps with callback hell / reasoning, but I think your argument was more about coordination. Hence the sliding buffer example - something that would be very, very hard to /coordinate/ with callbacks.
- deleted 12y ago[deleted]
- thesorrow 12y agoHow does this compare to FRP style ?
- jlongster 12y agoIt's more general than FRP so is better at stuff like simple async coordination (what most people use promises for). But you can easy do FRP-style stuff on top of channels, which is basically what transducers are. So they are closely related, but have different roots.
- gozala 12y agoRather than saying that CSP is more general, I'd say CSP is more provides you a more low level constructs. In FRP signals are the key concept that represent value that changes over time. Signals have a pushed based interface that's kind of why it's reactive. FRP typically provides pure functional interface, meaning you never put values or emit events, you just have control flow structures that allow you define transformations over base signals. FRP signals can be easily implemented via CSP channels, but not other way round, that's because CSP channels are push based for the producer side and pull based from the consumer side. If I had to make an analogy channels would be queues while signals would be an observable variable.
- neilellis 12y agoYou've got to wonder why exactly we still (in 2014) have to contort ourselves around a single threaded model. So that we end up with this level of complexity. JavaScript is great with data but is becoming a monstrosity when it comes to concurrency. Can we all stop and have a deep look at how other languages deal with concurrency. I have (like many of you) used many different languages and have played with several different concurrency models. The bottom line for me is that multiple threads + concurrency frameworks (i.e. no exposed concurrency primitives) are still the best solution. I appreciate JavaScript is trying to avoid deadlocking etc. but in modern concurrency frameworks this just isn't an issue. Seriously we're now contorting ourselves around dogma. Please browser folk, come up with a decent solution to save us all of this. VOTED DOWN FOR HERESY :-)
- jlongster 12y agoI think you've completely missed the point. CSP channels are in fact what are used for elegant parallelism on Clojure. The processes are backed by a thread-pool and can be run concurrently. Whether or not it's backed by real threads or not is completely opaque.
- neilellis 12y agoDo you feel that: var ch = chan(); go(function() { var val; while((val = yield take(ch)) !== csp.CLOSED) { console.log(val); } }); go(function() { yield put(ch, 1); yield take(timeout(1000)); yield put(ch, 2); ch.close(); }); Is clean and easy to understand. That's the point I'm making is that this contorting around a problem. I don't want my code littered with all this annotation just so that it can be synchronous. Also I'm not picking on the one solution, I just want everyone to take a step back and see if we're really heading in the right direction here.
- jlongster 12y agoIt's worth stepping back, and it's far easier than the alternatives for sure. (note that with macros you could even have nicer syntax). But yeah, if you're arguing for real threads, that's a different discussion. Even so, you'll have to do similar coordination between threads which will look similar.
- riffraff 12y agofunny, i read that as CPS and it still made sense.
- tracker1 12y agoWhat would be nice as an addendum to this, especially with the likes of browserify and webpack for node and the browser would be a syntax to start an async channel in a new process/webworker... var ch = new echan('moduleName'); Where the moduleName would be a module that exports a single function that receives two channels.. in, and out for a request/response pattern. An "easy" level of abstraction here where the request/response is only going to pass what works with JSON.stringify/parse, removing circular references. It could work really well for worker handlers... It only needs to be an abstraction around the csp interfaces, as well as the current implementations for web workers and forked processes in node.js More advanced scenarios could use 0mq for passing a worker to multiple processes... all of that said, it's just an idea. I think where this lines up very cleanly is as a means of communication with React and flux.
- pablovidal85 12y agoI translated the pingpong example to use events instead of CSP. https://gist.github.com/aynik/94c9f3d01139986d2b91 https://gist.github.com/aynik/94c9f3d01139986d2b91
- vfclists 12y agoWhy doesn't he state what CSP is upfront, requiring the reader to visit Wikipedia to know what it is? Buzz words and acronyms are getting out of hand on the web.
- kylebrown 12y agoEven mentioned transducers, cool! But, I was hoping for a treatment of CSP and react/flux. jlongster teased us about that here[1]. Maybe the next post in the series? (plz?) 1. https://justin.harmonize.fm/development/2014/08/05/om-and-flux.html#comment-1532327194 https://justin.harmonize.fm/development/2014/08/05/om-and-fl...