7 ms·
Show HN: Nsynjs – JS engine with stoppable threads and without callback hell
- modarts 9y agoWhat's wrong with async/await?
- q3k 9y agoIt's a kludge. Syntactic sugar to remove one level of nesting. Other languages come either with great concurrency support out of the box (Go, Erlang) or enough constructs to implement cooperative schedulers without having to specify async/await (Lua).
- vsviridov 9y agoWhat's wrong with that?
- cdata 9y agoNot disagreeing, but as a long time JavaScripter it is remarkable to me that no matter how delightful or expressive or ergonomic the language tries to become, the same old criticisms manage to evolve with it (this may not be unique to JS). [Edit] JS has long been criticized (fairly or not) for offering clunky "concurrency" strategies. If you must down vote, please have the decency to offer a counter perspective.
- Jim99 9y agoAs someone who has been around for a long time and manages teams using many different languages (C,C++,C#,Java,Python,JavaScript) my JavaScript/Web teams are the most problematic in terms of cost/performance/gating bugs/upgrades/multi-platform support. The JavaScript critiques that you see are just an expression of the time and resources being wasted.
- cdata 9y agoWhere in the stack did you spend your time before you became a manager?
- deleted 9y ago[deleted]
- sametmax 9y agoIf you have callbacks, you end up with hard to read and debug code. If you have transparent async, then: Then how do you know what blocks and what doesn't ? What's asynchronous and what's going to trigger a switch ? What's a disguised callback and what's the next line ? What's the solution then ?
- balfirevic 9y agoWhy would you need to know, except in some special cases? If you're using async/await, your next line is not executing anyway until the result comes, blocking or not.
- sametmax 9y agoBecause otherwise you block the even loop or mismatch life cycle. Espacially reading an unfamiliar code base.
- z3t4 9y agoembrace higher-order functions. Use named functions and closures! example code: var anchors = document.getElementsByTagName(“a”); for(var i=0,len=anchors.length; i<len; i++){ alertClickAnchor(i); // Named function } function alertClickAnchor(i) { // Closure anchors[i].onclick = function() { alert(i); } }
- kidstrack 9y ago2 main reasons: 1. If some nested function is async/await, all the callers (and whole graph) need to be converted to async/await. I feel that language shouldn't force programmer to do this type of tedious work. 2. It's not compatible with some browsers, only via Babel
- cdata 9y ago#1 is a misleading claim. An async function returns a promise when called, which can be used in any non-async context.
- Matthias247 9y agoI think the claim was: One async function (which of course returns a Promise under the hood) forces all surrounding functions to be also asynchronous (return a promise). Of course you could start an async operation from any function -> Just call the async function and ignore the result. But in order to do something with the result and return a transformed version of it the surrounding function has to be async (return a Promise, accept callbacks, etc) too. Maybe the confusion was the async here has two meanings: 1. asynchronous in general, which means it doesn't return a result immediately, but returns it through a Promise which is fulfilled later or a callback. 2. Using the async/await syntax. As we all agree this one is just sugar around Promises.
- sametmax 9y agoIn JS async/await returns a promise. In Python you have asyncio.ensure_future() to schedule coroutines. You can always call async code from sync code.
- camus2 9y ago> If some nested function is async/await, all the callers (and whole graph) need to be converted to async/await Is totally false. You can await on any promise, the method called doesn't have to be an async function. And you can resolve any async function through promises as well. > 2. It's not compatible with some browsers, only via Babel async/await is part of the the ES spec, which browsers have to follow to be compliant with ES spec.
- BinaryIdiot 9y agoWhile I don't use async / await right now, mostly because it's not natively available in all of the target browsers I want to use, I'm not the biggest fan of the pattern. It takes previously asynchronous functions and makes them appear as synchronous. The worst part is with some asynchronous methods you can't use async / await so now you have synchronous and asynchronous code that appears identical while also having some other asynchronous code that appears more traditional. Overall it just ends up being a bit inconsistent for my tastes. But I like that we're trying more things to evolve the language to avoid common pitfalls like callback hell
- BoorishBears 9y agoIt's funny watching part of the history of C# replay itself in Js, I heard the same arguments when it was playing out in C# (TPL => Promises, await/async => await/async)
- antonb9 9y agoI really enjoy the TPL library. blocking queue etc makes it pretty damn easy to understand, what could be complex code.
- spankalee 9y agoEven as a huge async/await fan, this is a great explanation of the problem: http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ http://journal.stuffwithstuff.com/2015/02/01/what-color-is-y... VMs that offer lightweight, blocking, non-shared memory, threads provide a great developer experience. The Dart team was experimenting with this with the Fletch VM.
- z3t4 9y agoWhen calling a function, you know what arguments/parameters to use, right!? Then you also know if it's sync or async. The browsers way of dealing with async seems to be forgotten, for example: button.onclick = buttonClicked; I find this pattern easier to deal with then callbacks.
- dahauns 9y agoWhile it gives good insight to the problem of sync vs async functions, I've come to find its conclusions problematic (and it rather blatantly ignores Chesterton's fence), especially with "Java did it right, but they have started to do it badly now", and especially "Go has eliminated the distinction between synchronous and asynchronous code". Ouch. You are going to think that - until your hit first deadlock or race condition. While implementation quality of the "colored function" concept varies greatly (and JS async/await is not a good example IMO - look at C# for one that doesn't neccesarily suffer the "async all the way up" problem, for example), there are reasons it's so prevalent. Async is fundamentally different, and more importantly: In the end, it's all about the data. That's why the most important part of goroutines is the channel/send/receive(EDIT: And especially select, of course. :)) implementation. And that's why the simple "go func" syntax itself or whether it's different from normal function is a bit of a red herring, since the implementation and data access/communication inside the function will likely be different.
- marcus_holmes 9y agoI don't know why you're getting downvoted, you're right. I love Go, it's my language of choice. There's a clear difference between calling a function sync or async. It's nice that we can choose to do either at will. Oh, except that if it's an async call we have to use channels to communicate with it. Which is cool, but it's a different mechanism than if it's a sync call. It's exactly the same as the red/blue rant about JS. If it's async you have to hand it a channel to talk to you on. If it's sync you can just wait for it to return. Async/Await same same but different. Yes, the language does some nice stuff under the covers about pausing goroutines, but it only does that if you have multiple goroutines. If you code everything without using goroutines (and channels) then it's not concurrent and won't do the nice stuff. It'll pause for i/o just like any other language.
- BinaryIdiot 9y agoSo interesting project! I'm skeptical on the practicality of it but it's still interesting. >> global.nsynjs = global.nsynjs || require('nsynjs'); Don't do this. The module pattern is pretty well known and you can use it to return a singleton. Global has some built in node.js stuff but I wouldn't mess with it. >> Example of wrapper to setTimeout, that will be gracefully stopped in case if pseudo-thread is stopped: This seems overly complex and unintuitive. Also, there are lots of references to `synjs` but the project's name is `nsynjs` which seemed confusing to me. Honestly, like I mentioned at first, cool project but callback hell is very easy to avoid even without Promises or async / await as long as you follow solid development patterns. I would be interested if you have benchmarks / comparisons against callbacks, promises and async / await.
- kidstrack 9y agoThanks for the feedback. "wrapper to setTimeout...This seems overly complex and unintuitive" Typical web app most likely would have very few wrappers ($.ajax, setTimeout, etc), and they need to be written only once. But then everywhere in nsynjs-executed code you can just use them, connect with any necessary logic that JS can offer (not only by chaining .then...then.), without thinking what function is async/await and when it actually executed. My intention was to be able to write logic on JS in step-by-step manner the same way as if it was Visual Basic.
- Kiro 9y ago> The module pattern is pretty well known and you can use it to return a singleton. How would you even make it _not_ return a singleton? I thought that was default.
- svckr 9y agoOne way is to delete entries from `require.cache`. Either way you might get a separate instance if npm decided that your module and another module require different version of a given module. These would both be singletons though. Just singletons of instances of different versions of the same module.
- BinaryIdiot 9y ago
- Neverbolt 9y agoCould you please not advocate SQLinjection in your example code? > friends: dbQuery("select * from firends where user_id = "+userId).data, > comments: dbQuery("select * from comments where user_id = "+userId).data, > likes: dbQuery("select * from likes where user_id = "+userId).data I'm no js developer, but there has to be a way of using prepared statements, even if just for sample code. It's not 2001 anymore, security is important!
- kidstrack 9y agoI agree with you. It's just for illustration purposes I intentionally oversimplified it to pseudo-code.
- Kudos 9y agoThat's the wrong thing to be oversimplifying, tbh.
- amelius 9y agoI don't see the problem if userId is guaranteed to be just an id. This can be done, for example, by testing it before the SQL call. In that case, it's safer than most pointer-dereferences done in C++.
- regularfry 9y agoThat's one hell of an `if` you've got there.
- Sorreah 9y agoNot that big of an if. The id was most likely pulled out of the database itself in cases like: >friends: dbQuery("select * from firends where user_id = "+userId).data
- Klathmon 9y agoor it was pulled from a GET parameter. The point is that regardless of where it came from parameterized queries are a staple of programming now, and having an example without it would be like having an example of a login system be if (username in db && password in db) { login() }
- drinchev 9y agoReminds me of `node-fibers`[1] var Fiber = require('fibers'); function sleep(ms) { var fiber = Fiber.current; setTimeout(function() { fiber.run(); }, ms); Fiber.yield(); } Fiber(function() { console.log('wait... ' + new Date); sleep(1000); console.log('ok... ' + new Date); }).run(); console.log('back in main'); It is used heavily in meteor[2] 1: https://github.com/laverdet/node-fibers https://github.com/laverdet/node-fibers 2: https://github.com/meteor/meteor https://github.com/meteor/meteor
- partycoder 9y agoWrong wrong wrong wrong, wrong wrong wrong wrong! https://www.youtube.com/watch?v=FPD5q6DC43M https://www.youtube.com/watch?v=FPD5q6DC43M JavaScript is not multithreaded. Web workers would be the closest to that but are not used by this library. Then, promises are a much better abstraction for this since they are not only about result propagation but error propagation. Then, promises can be made cancellable.
- pygy_ 9y agoGreen threads are threads too (a.k.a. cooperative threads/coroutines).
- partycoder 9y agoIt is my understanding they would always execute on the same core.
- camus2 9y ago> It is my understanding they would always execute on the same core. no they don't, Go has green threads and they are fully parallel. They are called green because they are not scheduled by the operating system.
- partycoder 9y agoI was referring to node.
- maaaats 9y ago> Wrong wrong wrong wrong, wrong wrong wrong wrong! https://www.youtu.. https://www.youtu... What kind of person do you have to be to act like this when people try to show what they have made? Very sad.
- partycoder 9y agoHave some sense of humor. I would not take that literally / seriously. I would rather focus on the next paragraph which is the one that matters.
- nialv7 9y agoI can't quite see the need of this now we have async/await.
- meirelles 9y agoMe too. For the sake of sanity we should stick with async / await and forget the time we had to choose from dozens of different ways of doing async code (most of time requiring tedious wrappers). Lets the winner takes it all.
- z3t4 9y agoasync/await doesn't change the fact that we have two types of functions, async and sync.
- wwwigham 9y agoSo it stringifies the function you give it, splits it into its component bits of execution, then interprets the contents alongside a state machine (with judicious use of bits concatenated together and eval'd). Interesting, for sure. AFAIK there's no preemption mechanism (or resource management), so all it does is make your code execute asynchronously - very asynchronously - the every-line-interwoven-randomly kind of asynchronously. I do love me some metaprogramming, but is there a real scenario where you'd want something as dangerous as this compared to a generator (or a system of generators)? They have very clear atomicity guarantees (things between yields will happen synchronously), unlike what this ends up decomposing your code into. I suppose that's just the cooperative vs supervised threading debate, though?
- caub 9y agofor callback-hell, there's async/await for theeads, there are ways too
- tobyhinloopen 9y agoHow is this an improvement over `await` and `async`?
- forgottenacc57 9y agoThe JavaScript callback hell thing is pretty much solved now isn't it?
- Can_Not 9y agoSightly related question, is there a library that - takes in a function and returns a promise returning function - the new function will use a web worker in the browser and something like a thread worker in NodeJs. - isomorphic, as in same API in browser as in the server (so maybe usable in nextjs and nuxtjs based applications Just curious if anything like that exists.
- vbezhenar 9y agoI'm using ES6 async/await and I can't be happier, async programming is almost sane now. The only drawback is that you have to remember that it's all syntax sugar about Promises and they are just a bit more than syntax sugar about callbacks, so you have to understand how each async thing works or you'll be mad. But when you know those things, you can be asynchronously productive.