Skip to content

Instantly share code, notes, and snippets.

@melissamarima
Created October 18, 2015 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melissamarima/ea2e4c7c91ec4c061c08 to your computer and use it in GitHub Desktop.
Save melissamarima/ea2e4c7c91ec4c061c08 to your computer and use it in GitHub Desktop.
Trying to understand JS concurrency and promises
10-16-2015 freenode.irc #javascript
22:24] <melissamm> I still don't understand why it's so bad to force synchronous functions in the async node.js MEAN stack. Sure it waits around, but wouldn't promises also have to wait around to get resolved?
[22:25] <melissamm> (sorry my internet died for a bit, I might have not caught the answers to my previous question.)
[22:25] <oojacoboo> melissamm: the async nature of js is important
[22:25] <oojacoboo> it's the nature of how people read and interpret it, it's also one of the key benefits of the language
[22:26] <oojacoboo> if you want sync, use another language
[22:26] <melissamm> I think I'm missing something. Promises still waits around to get resolved. So that also takes long.
[22:26] <melissamm> nono I have to use Async, I'm using the MEAN stack
[22:26] <oojacoboo> melissamm: yes, and promises are optional
[22:26] <oojacoboo> MEAN stack?
[22:26] <melissamm> or are you saying that promises is just doing sequential stuff the async way?
[22:26] <melissamm> MongoDB/Mongoose, Express, AngularJS, Node.js
[22:27] <oojacoboo> melissamm: don't look at it in terms of sequential or not
[22:27] <oojacoboo> melissamm: it's a "promised callback"
[22:27] <oojacoboo> yes, it will call upon the completion of the previous event, but it's more like a callback
[22:27] <oojacoboo> it's just registered instead of explicitly called
[22:28] <melissamm> oojacoboo, it's still more like a callback ... so it frees up the server to do other random stuff
[22:28] <melissamm> right?
[22:28] <Sorella> melissamm: JS environments are usually single-threaded. "Synchronous" do not fit that, since it's at odds with "Concurrency" (which you want). There's also a problem with sequential-looking code that it tends to be (1) inefficient; (2) non-composable. async/await in ES7 has those problems.
[22:29] <oojacoboo> melissamm: the server/client/computer can execute other code alongside the main event/function as well as the callback/promise
[22:29] <Sorella> Promises let you do concurrency by specifying how your computations depend on some data, and then having something else figure out how to execute your program in the correct order.
[22:29] <oojacoboo> it's just that there is a relationship/order to those two functions
[22:29] <melissamm> "can execute other code alongside the main event/function " like if it's running 2 people's code, right?
[22:30] <oojacoboo> melissamm: umm, maybe at the server level
[22:30] <oojacoboo> but I'm talking more at the process/instance/request level
[22:30] <oojacoboo> two of your functions within the same file can run at the same time in js
[22:31] <dostoyevsky> melissamm: you could define your own function a(i,s,o,g,r,a,p,h) and randomly make one of these parameters a callback... you would only know from reading the documentation, or source code of that function... with promises you'd know what's supposed to happen by just looking at how f() is being called
[22:31] <oojacoboo> a promise tells one to run after the other
[22:31] <Sorella> dostoyevsky: you wouldn't, really.
[22:31] <dostoyevsky> Sorella: Wouldn't what?
[22:32] <Sorella> dostoyevsky: you have the same problem with promises and callbacks, because JS is a dynamic language, and both cases are dynamically dispatched (i.e.: only resolved at runtime, depending on which value you've got)
[22:32] <deltab> oojacoboo: "at the same time" sounds wrong
[22:33] <Sorella> They can run at the same time in Nashorn :P But most JS implementations are single-threaded
[22:33] <oojacoboo> deltab: okay...?
[22:34] <Sorella> So no piece of code can ever run at the same time as another piece of code in Node, Chrome, Firefox, Safari, ...
[22:34] <melissamm> I guess my confusion comes from the fact that I'm having a server that I think just runs that function. When that function runs, it should be run sequentially. But I guess what I'm hearing from you guys is that even if only that function runs on the server, there could still be other processes or threads running because computers are good at task switching and multitasking. I only give the server one function to run, but the server probably has other things to run
[22:34] <melissamm> like background processes
[22:34] <melissamm> is my understanding correct?
[22:34] <deltab> oojacoboo: maybe you're trying to say something else, but the way I read it, saying two functions run at the same time in js is wrong
[22:34] <oojacoboo> Sorella: you should write your code as though they'll run at the same time
[22:35] <rcyr> melissamm: Yes, you could see async functions as being "background processes"
[22:35] <oojacoboo> assuming they'll run at the same time is generally the best way to write your js
[22:35] <Sorella> melissamm: it depends on what your server is.
[22:35] <melissamm> what is my server?
[22:35] <Sorella> melissamm: if it's Node, and your function is entirely synchronous, then nothing else will run during the time that function is running.
[22:35] <deltab> oojacoboo: you can have one function paused while another runs, and with generators even have them alternating, but there's still only a single thread
[22:35] <melissamm> How do I answer your question? It's a Node.js server
[22:36] <Sorella> If it's Nashorn, you can run things in parallel, even if your function is entirely synchronous.
[22:36] <oojacoboo> deltab: for many servers, yea
[22:37] <Sorella> melissamm: so, if you mean "synchronous," that function is the only thing that will get run until it finishes executing. If you mean "sequential," then you can have some interleaving (though no parallelism, no data races -- if you keep your operations atomic, -- etc). The background processes in Node can't affect your JS code, since Node uses a single thread
[22:37] <Sorella> for running JS.
[22:38] <deltab> you can have non-JS threads running though
[22:38] <melissamm> Sorella, I don't know if they could be sequential
[22:38] <Sorella> Interleaving only happens when you yield to the VM (i.e.: call some asynchronous routine, and stop executing JS code)
[22:38] <deltab> doing things like http requests, sending and receiving data from other processes, etc.
[22:39] <melissamm> Sorella can you give me some pointers to sequential stuff vs synchronous stuff?
[22:39] <melissamm> I don't know what I can have
[22:39] <deltab> https://www.youtube.com/watch?v=8aGhZQkoFbQ&feature=youtu.be
[22:39] <Sorella> melissamm: `var c = a + b; var d = c + 1` is synchronous, and sequential. `add(a, b, function(c){ add(c, 1, function(d){ ... }) })` is sequential, but not necessarily synchronous.
[22:40] <melissamm> deltab is that youtube for my question or something else?
[22:40] <deltab> yes
[22:40] <dostoyevsky> Sorella: how is what oyu saying different from saying that in javascript ";" or "\n" don't guranttee order of execution? It's merely a convention to structure code that way but there is a convention missing for callbacks... you want to understand code easily by reading it without having to traverse into other definitions, and that's what promises does... even though like with ";" and "\n" it's not really a guarantee
[22:40] <deltab> at least it could be helpful in understanding what happens inside node
[22:42] <Sorella> dostoyevsky: JavaScript guarantees order of execution. In `a; b`, `a` is always guaranteed to execute completely before the engine moves to executing `b`. With callbacks and promises you (1) don't have that guarantee, because order of execution is defined by the dynamic execution of your program; (2) can't tell what is a callback and what is a promise
[22:42] <Sorella> because JS has no types.
[22:44] <deltab> setTimeout(a, x); setTimeout(b, y); // which runs first, a or b?
[22:44] <dostoyevsky> Sorella: I could litter my code with gotos as well, to make you not assume any order of execution, no? :)
[22:45] <melissamm> Sorella: I love your example with the additions. Is it true that "`var c = a + b; var d = c + 1" would always give the same answer if the variables are set to the same numbers. BUT "`add(a, b, function(c){ add(c, 1, function(d){ ... }) })` " would not give the same answer?
[22:45] <Sorella> dostoyevsky: JS doesn't have gotos.
[22:46] <dostoyevsky> Sorella: it's called switch in js :)
[22:46] <Sorella> melissamm: if you define `function add(a, b, Return){ Return(a + b) }`, then you'll get the same answer in both. The difference is mostly that the `add` example isn't limited to JS's order of execution.
[22:46] <Sorella> dostoyevsky: switch isn't goto.
[22:47] <Sorella> (yes, you can, of course, write `while (true) switch(label) { ... }`, and put your entire program inside `...`. That requires you to also have ZERO function calls, and ZERO function definitions. No one writes code like that)
[22:49] <melissamm> Sorella, I guess in addition order doesn't matter. If your example were division, would interleaving cause different answers to come up potentially?
[22:49] <Sorella> melissamm: no. Both examples are sequential. They have a consistent order.
[22:50] <Sorella> melissamm: the things that can be interleaved in the second example don't have any relationship with the computation that's running in that example.
[22:50] <melissamm> what can be interleaved in the second example then?
[22:50] <Sorella> (You could, of course, have problems if you're mutating parts of a data structure shared by two different parts of your code)
[22:50] <dostoyevsky> deltab: setTimeout is not part of the ECMA spec, right?
[22:52] <melissamm> Sorella, is the interleaving in Node.js the same as other languages? Can I just read any article online about interleaving and learn more?
[22:52] <dostoyevsky> deltab: so what happens with ``setTimeout(a, x); setTimeout(b, y)'' is not standardized...
[22:55] <Sorella> melissamm: for example, `function sum(x, cc){ setTimeout(function(){ cc(x.l + x.r) }, 100) }; var a = { l: 1, r: 3 }, b = { l: 4 }; var A = sum(a, function(r) { sum({ l: b.l, r: r }, print) }); var B = setTimeout(function(){ a.l = 3 }, 10); var C = setTimeout(function(){ b.l = 6 }, 100)` has three different processes: A, B, and C. Since B and C happen during
[22:55] <Sorella> A, and modify a variable A uses, you get a similar set of problems data races in languages with pre-emptive threads have.
[22:56] <dostoyevsky> Still, there is that: https://html.spec.whatwg.org/multipage/webappapis.html#dom-windowtimers-settimeout
[22:56] <Sorella> melissamm: it's similar to languages with other forms of cooperative concurrency (generators in Python, coroutines in Lua)
[22:57] <Sorella> goroutines in Go are probably cooperative as well.
[22:58] <Sorella> melissamm: if you're not familiar with the differences between preemptive concurrency and cooperative concurrency, learning that will probably help you quite a bit understanding the limits and benefits of concurrency in Node.
[22:58] <melissamm> Sorella thank you so much. I have to go soon. Are you usually on this chat room?
[22:59] <Sorella> I'm around a fair amount of time, I suppose.
[22:59] <melissamm> I still have to take some time to digest the stuff you wrote. What do I do if I have follow-up questions?
[23:00] <Sorella> melissamm: you can tweet me (@robotlolita) or email me (queen at robotlolita.me). Or you can just ask here, other people might also be around to answer
[23:02] <melissamm> Sorella. Awesome thanks so much!
[23:04] <melissamm> thank you oojacoboo, dostoyevsky, and deltab for helping out as well. Have a great weekend everyone.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment