Show HN: Nsynjs – JS engine with stoppable threads and without callback hell
github.com
github.com
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?
>> 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.
"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.
How would you even make it _not_ return a singleton? I thought that was default.
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.
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 2: https://github.com/meteor/meteor
> 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!
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++.
>friends: dbQuery("select * from firends where user_id = "+userId).data
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() }There are valid cases where you're sure that the thing you're looking at is a valid id (ie. you already pulled it out of the database or by generating it yourself), not every program is a webapp that's handling user input, and examples like this aren't meant to teach you best security practices.
And yes the login system example would be acceptable if you're discussing something entirely unrelated to actually implementing one.
dbquery('select * from friends where user_id = $1', userId)
A few extra characters is all it takes.And the benefits of prepared or parameterized statements don't end at security, they can often have performance benefits as well.
And as for the login pseudocode, if it doesn't have anything to do with the example, hide the implementation:
if (userIsAuthenticated === true) { login() } dbquery(sql`select * from friends where user_id = ${userId}`)
https://www.npmjs.com/package/sql-template-stringsTemplate strings are the one ES2015 feature I still really haven't used much. And this almost seems like a textbook use case for them! I'll need to give this a shot in a toy project and see if I can't get my own version hacked together for support with my favorite database interface library in node (pg-promise)
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.
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.
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.
button.onclick = buttonClicked;
I find this pattern easier to deal with then callbacks.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
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).
[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.
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 ?
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);
}
}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.
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.
- 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.
Lets the winner takes it all.