Live data from Hacker News

Interview with Ryan Dahl, Creator of Node.js

mappingthejourney.com

121–130 of 235 posts

Re: Interview with Ryan Dahl, Creator of Node.js

#121

Earlier quoted context omitted.

On that note, coming back from node.js has been a really frustrating experience for me. I want to scream every time somebody suggests threading as a solution to non-blocking database calls and HTTP requests. It's made me painfully aware of how often parallelism is suggested in place concurrency. C# in particular does a great job at conflating concurrency and parallelism. Both fall under the same Task namespace and it…

but why? Go's model is perfect. They're not real threads, it's basically very similar to Node, except that you can write code without a mess of callbacks and it's easier to reason about...

Not just that. It can use multiple OS threads and multiplex the goroutines on actual threads so programs can actually leverage multiple cores.

Re: Interview with Ryan Dahl, Creator of Node.js

#122

In this thread: people who don't use Node.js making wild presumptions about how it works. Callback hell? Been a few years since that's been a problem.

It depends :tm:.

There are still a lot of codebases that are callback heavy. For one, callbacks are faster than promises in a lot of node versions by a very large margin. In other code bases, legacy rules still apply.

Promises don't work well for some more complicated logical flows (though they're pretty damn perfect for the common ones) and async is still pretty new.

Just because it's not a problem you deal with doesn't mean that it doesn't still affect plenty of devs.

Re: Interview with Ryan Dahl, Creator of Node.js

#123
post #111

Earlier quoted context omitted.

I should definitely make a macro at this point: Callback paradigm has not been used in node development for 3-4 years at this point. return someHttpCall() .then(response => someOtherHttpCall(response)) // Do 2 async operations in Parallel: .then(response => Promise.join( someCacheThing(response), someDBThing(response) )) .spread((cacheResponse, dbResponse) => sendBackToClient()); This isn't callback hell. Without cre…

I'm well aware of promises, thank you. I'm also well aware that there's very little difference in reality between a promise-based style of coding and a callback one. You still lose stack continuity, it's still much harder to chain operations that hop stacks, it's still a nightmare to debug compared to stack-based programming, etc. If you've ever actually implemented a promise it's even easier to see how little promis…

How do you get stack continuity in anything that is multithreaded unless the debugger adds special support for it?

Re: Interview with Ryan Dahl, Creator of Node.js

#124

Earlier quoted context omitted.

> Many are forgetting the initial reason node.js became popular. Consider the popular server-side landscape before node.js. It was dominated by Java, Python, etc. The primary way these ecosystems handle concurrency is OS-level threading. There was nothing else in the popular languages. What? I am sorry but this is not true. Coroutines have been a concept for...well a long time: https://en.wikipedia.org/wiki/Coroutine…

>Coroutines have been a concept for...well a long time: ... Green threads also have been around for a while. What web frameworks were built around using them? Was there a good ecosystem of libraries that were easy to use with the web framework without introducing blocking I/O? >I am not sure how you can say this while using Python as an example. Python has the GIL which, typically viewed as a limitation, actually pre…

I often wonder why Python's gevent didn't become more popular. It would monkey patch the socket libraries to yield to an event loop, allowing you to magically use blocking code and libraries with practically zero code changes, and zero callback hell. I imagine it had to do with marketing - when Node was released, everyone thought the spaghetti horror that was Twisted was the only other event-loop-based game in town.

Ironically, now that we have async/await to replace nested callbacks, Node finally has the code readability that gevent users took for granted all this time.

Re: Interview with Ryan Dahl, Creator of Node.js

#125
post #108
post #103

Earlier quoted context omitted.

Make a native app for every independent platform?

Windows, Linux, OSX - there just aren't that many platforms these days, it's perfectly do-able. If your core logic is in ANSI C (or equivalent) and you just need a GUI for each platform, even easier.

It's still 3 more platforms, which means 3 more developers, which leads to more $$$. Not everyone is VC backed with multi-millions.

Re: Interview with Ryan Dahl, Creator of Node.js

#126
post #111

Earlier quoted context omitted.

I'm well aware of promises, thank you. I'm also well aware that there's very little difference in reality between a promise-based style of coding and a callback one. You still lose stack continuity, it's still much harder to chain operations that hop stacks, it's still a nightmare to debug compared to stack-based programming, etc. If you've ever actually implemented a promise it's even easier to see how little promis…

First of all, I have absolutely implemented promises from scratch, and it IS trivial. However, "callback hell" is a reference to writing code with deeply nested callbacks, particularly with manual error handling at each level, both of which promises completely negate. If you want to change the topic from "callback hell" to debugging across stacks, then we can do that. There was some work with "domains," since moved t…

It's still "callback hell" because you're still fundamentally writing code where you invoke an API and pass in a callback to handle the results. The fact that the callback you pass in happens to be a promise that allows you to stage other callbacks and/or promises doesn't really change things enough for the label "callback hell" to be inaccurate in my opinion.

A different programming paradigm, for instance, would be the use of delimited continuations such that the API you invoke suspends the current call stack, executes the I/O operation, then resume the call stack with the result of the I/O operation. Very few languages support that. One reason is that natively supported continuations in the programming language has far reaching consequences in terms of performance.

I'm not an expert on golang, but I believe this is essentially how goroutines are implemented: https://groups.google.com/forum/#!msg/golang-nuts/t3g8NbITYE...

Also keep in mind that I'm not 100% against callback-based programming. I have, for instance, implemented a non-blocking client for a custom TCP-based protocol using Netty. The client performed better than a blocking version that it was meant to replace. I played around with using Promises in conjunction with the library but ended up preferring callbacks to Promises for a number of reasons, some of which are specific to the JVM.

Re: Interview with Ryan Dahl, Creator of Node.js

#127
post #111

Earlier quoted context omitted.

I'm well aware of promises, thank you. I'm also well aware that there's very little difference in reality between a promise-based style of coding and a callback one. You still lose stack continuity, it's still much harder to chain operations that hop stacks, it's still a nightmare to debug compared to stack-based programming, etc. If you've ever actually implemented a promise it's even easier to see how little promis…

How do you get stack continuity in anything that is multithreaded unless the debugger adds special support for it?

By programming using synchronous blocking code within a single thread, of course.

Re: Interview with Ryan Dahl, Creator of Node.js

#128

Many are forgetting the initial reason node.js became popular. Consider the popular server-side landscape before node.js. It was dominated by Java, Python, etc. The primary way these ecosystems handle concurrency is OS-level threading. There was nothing else in the popular languages. Each language had some niche library that did non-blocking I/O (Twisted for Python, Netty for Java), but these all had a critical flaw,…

You're getting a lot of pedantic replies, but your post is spot on. At the time it arrived, asynchronous operations were close to impossible in PHP, very difficult and awkward in .NET, and very uncommon in Java. In Node it not only was possible, it was impossible (without going to great efforts) to do otherwise.

People have a short memory, but at the time getting single to double digits of requests per second on a beefy server was entirely typical. Yes, someone somewhere could demonstrate an alternative, but node completely changed what was normal. It was extremely high performance for the time.

Re: Interview with Ryan Dahl, Creator of Node.js

#129
post #108

Earlier quoted context omitted.

Windows, Linux, OSX - there just aren't that many platforms these days, it's perfectly do-able. If your core logic is in ANSI C (or equivalent) and you just need a GUI for each platform, even easier.

It's still 3 more platforms, which means 3 more developers, which leads to more $$$. Not everyone is VC backed with multi-millions.

But one of these "offline" apps has to work in Firefox, IE and Safari, so really, it's no different

Re: Interview with Ryan Dahl, Creator of Node.js

#130

Earlier quoted context omitted.

On that note, coming back from node.js has been a really frustrating experience for me. I want to scream every time somebody suggests threading as a solution to non-blocking database calls and HTTP requests. It's made me painfully aware of how often parallelism is suggested in place concurrency. C# in particular does a great job at conflating concurrency and parallelism. Both fall under the same Task namespace and it…

It's hardly the fault of the language if people are lying in their method signatures. I'm not aware of a mainstream PL with a type system that is powerful enough to avoid something like that.

In this case, the .NET-provided base class defaults to using the synchronous version when the async version hasn't been overridden.

https://msdn.microsoft.com/en-us/library/system.data.common....

> Providers should implement this method to provide a non-default implementation for ExecuteReader overloads.

> The default implementation invokes the synchronous ExecuteReader method and returns a completed task, blocking the calling thread. The default implementation will return a cancelled task if passed an already cancelled cancellation token. Exceptions thrown by ExecuteReader will be communicated via the returned Task Exception property.

Found that after several hours of tearing my hair out trying to figure out why my async calls were still blocking...

Post reply on HN