5 ms·
> Another way of solving this problem comes from the realisation that we only really need to keep track of the dependencies for a promise while the promise is i
by wonnage 11y ago
> Another way of solving this problem comes from the realisation that we only really need to keep track of the dependencies for a promise while the promise is in the pending state, because once a promise is fulfilled we can just execute the function right away!
This is a common gotcha in Javascript implementations, in that you think you want this, but you really don't! Now you never know if your code is synchronous or will run in a subsequent tick. Your call tree will look completely different depending on race conditions...
This comes up in user code as well; any time you write a function that takes a callback, it's probably a good idea to either always run it either in the same call tree or in a new stack, but never mix the two. It's usually easier to just do the latter using process.nextTick.
- tlrobinson 11y agoPromises also solve this problem. If you immediately resolve a promise it isn't actually resolved until the next event loop "tick": new Promise(resolve => resolve("resolved!")).then(result => console.log(result)); console.log("next statement"); Prints "next statement" then "resolved!".
- jallardice 11y agoYou don't even have to resolve the promise via a callback for that to be the case - you can use the static resolve method. This is really useful if you have a function that can sometimes return a promise and sometimes a "normal" value. Promise.resolve("resolved!").then(result => console.log(result)); console.log("next statement");
- mistercow 11y agoIt's actually not the next event loop tick (or it's not supposed to be; some implementations get this wrong). Promises use microtasks, so an already-resolved promise dispatches at the end of the current tick.
- erikpukinskis 11y agoI get what you're saying, but for some reason it doesn't feel right to me. Part of it is that if your API requires you to think about whether or not it will run in the current or next tick, that's probably not the right API. I find in JavaScript it's best to just assume your callbacks could be called at any time, in any order. And if you need a specific priority then write some code that actually explicitly orchestrates that.
- viperscape 11y agoI find that hard to do when some libraries make heavy use of async, you basically have to bend to the library when writing your own code
- erikpukinskis 11y agoI don't blame you. I basically don't use any libraries any more because the proliferation of promises (and libraries with promise-like architectures) has made everything impossible to reason about or debug. But I have the luxury of being a wizard in the forest who answers to no one.
- Rauchg 11y agoI think you're maybe referring to a broken `Promise` implementation. Here's a good article about how callbacks get scheduled: https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ https://jakearchibald.com/2015/tasks-microtasks-queues-and-s...
- wonnage 11y agoOh yeah, I don't think any real/production Promise implementation behaves this way - but it can be unclear why. As a beginner, you might expect Promise.resolve('foo').then(...) to happen immediately, as the quoted passage suggests; I was trying to get at why that's not the case.
- btilly 11y agoThis is a common gotcha in Javascript implementations, in that you think you want this, but you really don't! No, I really, really, DO want this. And I want my entire codebase written in such a way that this is fine. You need consistent abstractions to make asynchronous logic flow comprehensible. And once you have them, stick to them rigorously. Promises are such an abstraction. Build on it, don't ruin it. Yes, there are lots of ways to ruin it. And for every way it can be ruined, there is a way to make it work without breaking the abstraction. Do the latter.
- vectorjohn 11y agoI think you (or I) misunderstand what you're replying to. When they said "you really don't want this", they're saying you don't want promises to sometimes be async and sometimes resolve in the same tick. Always make them async. That agrees with you, since it would mean you can always treat promises the same.
- dvdcxn 11y ago>sometimes be async and sometimes resolve in the same tick That's still asynchronous though isn't it? (Correct me if I'm wrong I'm just spitballing, still learning). There's no lower bound on the minimum amount of ticks a process can take for it to be async. What gives it that async-ness is that the upper bound is unknown, indeterminate, and changeable. Ergo, if some process is sometimes synchronous, and sometimes asynchronous, it's really a process that is asynchronous, but just so happens to occasionally execute in synchronous-like time.
- wonnage 11y agoThe meaning of 'tick' here is special, since we're talking about Node. It's not a measure of time, it's an iteration of Node's event loop. Because Node is single-threaded, everything that happens in a single tick (i.e, one run of the event loop) is in the same execution context/stack/call tree/whatever you want to call it. So we generally call this "synchronous", although technically you could be holding onto the tick forever, firing off a bunch of nonblocking IO in there and doing your own polling/event management. Of course, that would be silly, since Node manages an event loop for you. So your nonblocking IO would instead push events onto the queue, and let Node move on to the next tick. If something happens in a different tick, it gets its own clean slate of an execution context, and we call this "async", since the function that triggered it is no longer running.