4 ms·
Handling Errors in IcedCoffeeScript
- jashkenas 12y agoHere's Chris' comment from when this was posted (but didn't make it to the front page) yesterday: --- malgorithms 22 hours ago | link I think the great thing about IcedCoffeeScript + the ESC library is how it fits into more complicated flow logic, while allowing easy refactoring. Max doesn't really get into the otherwise impossible examples in his post. Even if you're firing off RPC's awaiting in the middle of a loop or switch statement, you can move logic around just by shifting individual lines. Consider how simple this looks: for user_id in user_ids await load_user user_id, esc defer user user.whatever() # etc., with user Writing that in plain Coffee or JS is impossible; using a pure async library is sort of possible but impossible to refactor.
- malgorithms 12y agoTo elaborate, a nice thing about Iced is the simplicity, even inside flow logic, to refactor async code. # serial for uid, i in uids await load_user uid, defer users[i] All I do is move the await: # concurrent await for uid, i in uids load_user uid, defer users[i] As you can imagine, this would be radically different JavaScript, yet it's (1) easy to read Coffee, (2) easy to refactor, and (3) runs on any browser. The ES6 stuff is new, and I can't use it because I'm writing for both Node and the browser, but can someone tell me how the above refactor would go?
- aikah 12y agoYou cant really do that in ES6.You'd have to use a co-routine framework (and a "thunkifier") and a generator that would yield some stuff. something like co(function *(){ for(i in uids){ users[i] = yield thunkify(load_users)(uids[i]); } }); While generators are useful, they dont make async code look like sync code.
- sync 12y agoAnd here's how to do the same in plain JS with ES6, available now in node (--harmony) and (I believe?) Chrome Canary. function *() { try { let body = yield request("https://x.io/"); return yield request("https://x.io/?q=" + body.hash); } catch (e) { // do what you like with the error } }
- jashkenas 12y agoAnd here's how to do the same in plain CoffeeScript with generators — using a new patch landed a couple of minutes ago: https://github.com/jashkenas/coffeescript/pull/3240/files https://github.com/jashkenas/coffeescript/pull/3240/files -> try body = yield request "https://x.io/" yield request "https://x.io/?q=#{body.hash}" catch e # do what you like with the error ... the salient bit being that there's no need to declare a generator function as a "special" type of function different from any other — a generator is simply a function that yields.
- jb55 12y agoNote that this is just a generator yielding callback functions/promises. You need an interpreter such as co to actually run them.
- STRML 12y agoThis is a really nice alternative to Promises, which I have grown to really love in the last few months - especially since bluebird (https://github.com/petkaantonov/bluebird https://github.com/petkaantonov/bluebird) handles errors really sanely. It takes a lot of getting used to but it is really, really nice to be able to surround error-prone code in what amounts to a try/catch, with a single catch that can (like Java) branch based on error type. For a second it feels like sync programming. As cool as ICS is, I strongly prefer the yield syntax to the await/defer syntax. It's a single keyword and it's much more obvious where the value is coming from. Plus, it's going to be everywhere soon. At keybase, do you guys intend to continue with ICS or eventually move to ES6?
- maxtaco 12y agoWe'd like to reimplement ICS using ES6, but keep the await/defer syntax and semantics as they are. The current ICS is a big modification to CoffeeScript, and maintaining the patch is tricky. Hopefully ES6 will ease that headache. But we can't make this change until people's node.js installs have caught up, which might take a while.
- Touche 12y agoYou can just use Traceur.
- ashtuchkin 12y agoAfter my 3 years coding CoffeeScript, I cannot live without 'errTo', similar helper I wrote a while ago: errTo = require 'errto' readDirectoryAsync = (catalog, cb) -> fs.readdir catalog, errTo cb, (filenames) -> # Notice no 'err' argument. # Error check is done automatically in errTo and cb(err) is called on error. # Subsequent code is called ONLY when no error given. callback null, filenames # Express sample. app.get '/', (req, res, next) -> readDirectoryAsync __dirname, errTo next, (filenames) -> # Use Express error handling by calling next(err) res.send filenames https://github.com/ashtuchkin/errto https://github.com/ashtuchkin/errto