You can't tell whether or not something is using "threads" or not just by looking at it. Javascript is a fairly standard Algol language with a modestly unusual object model, and if all you know is other Algol languages you may not realize what is possible. There are numerous languages where you can write the equivalent of:
function do_something():
socket = wait_for_a_socket()
data = read_everything_from_socket(socket)
process_data_long_and_hard_with_lots_of_io(data)
write_to_disk(data)
return_result(socket, data)
Where, as my function names imply, further code may be called that does things like talk to databases, or wait for other data, or any amount of other I/O, and you may not have to write a single asynchronous callback. Why? Because unwrapping code into continuations and managing them in the runtime is a
trivial compiler transformation when you design your language to work like that from day one. Like Erlang, or, in this case, Clojure.
The fact that Node.js requires you to manually shatter your code into teensy-weensy little fragments and manually wire it back together is a hack which should not be mistaken for a feature. Javascript requires you to do that, because it's an Algol language and just doesn't work any other way. If that's what you love doing, great, but that's an awful lot of time and effort spent on writing plumbing (and debugging plumbing, and debugging nontrivial asynchronous plumbing in a mutable language isn't in the worst tier of programming tasks in the world, but it's solidly in the second...) that you could have been spending on writing code that actually solves customer problems.
(I am aware of the libraries that pretend to help this. They are a joke compared to working in a language that actually supports this. I can call functions and send messages and read files and read from databases and write functions to abstract all this and I don't spend one second wondering how I'm going to wire all the pieces together at runtime. No amount of code slathered over Javascript can match that, short of an entirely new language that compiles into Javascript. (Which is inevitable. And it will be hailed as a brilliant breakthrough.) All of the libraries I was pointed to last time I brought this up use the exact same obvious hack, which helps with the case of stringing a handful of teensy-weensy fragments of code onto a single string but can't handle anything more.)