3 ms·
> Both of these functions may be synchronous, and may return values. Thus That promise chain is not synchronous. You can prove this by putting your code sample
by KirinDave 8y ago
> Both of these functions may be synchronous, and may return values. Thus
That promise chain is not synchronous. You can prove this by putting your code sample and a following console.log("meep") into a function. The console.log("meep") will always fire before your promise's final handler runs, when you call the function. That's because it's scheduled after your calling function returns.
Try it.
> Will print 4, not undefined.
That's indeed true, but it's a special property of promises that you can extend the construction of a callback with `then` calls. You can never return that value to the calling context. Creating the illusion that you can is what async/await is for. The promise context extended the computation to the final callback, which executed the side effect.
It would be a much neater implementation if the underlying resolve/reject functions that construct the promise were synchronously calling the functions supplied by then. That'd be awesome. Sadly, that's not possible with this implementation, because you can then-extend a resolved promise. But I confess I like how algebraic this implementation is.
It's not wrong to call a then-extension a "callback" if it's the final one in the chain. It's computed value is forever discarded, as ultimately is the value of the entire promise. All promises terminate with a callback who's value is discarded.
As I said, Promises are special and expose a continuation monad, in that they're a way to construct callbacks piece-wise. It's a very useful piece of functionality for JavaScript to have and enables the underlying syntactic transformations that make async/await work.
- joshuamorton 8y ago>That promise chain is not synchronous. The promise chain is executed synchronously in an asynchronous context. You seem to misunderstand this nuance. `x => x + 1` is a synchronous function. It will always execute synchronously and will return a result when it is invoked and block (within its context) until that invocation is complete. However, its calling context may be paused/pre-empted. Importantly though, the promise won't be pre-empted during the evaluation of a synchronous function: function sleep(ms) { var start = new Date().getTime(), expire = start + ms; while (new Date().getTime() < expire) { } return; } Promise.resolve(0).then( (x) => { for (i = 0; i < 15; i++) { sleep(1000); console.log(`doing stuff ${i}`); } }).then(console.log); If you run this in your console and then try to do anything, you will be unable to. You'll be blocked by the asynchronous code (because it never releases). Replace my blocking sleep with setTimeout, a nonblocking alternative, and you'll find that things work normally. You're executing synchronous, blocking code in an asynchronous context. Promises aren't doing anything magical, they're simply syntactic sugar for flattening otherwise nested chains of this (where +1 is a standin for the action that this specific function is taking): f = (cb, v) => cb(v + 1) which quickly balloons to f = (cb, v) => cb(v + 1) (v) => (f(console.log, v)) f((v) => (f(console.log, v)), 1) f((v) => (f((v) => (f(console.log, v)), v)), 1) back to something sane: Promise.resolve(1) .then(f) .then(f) .then(f) .then(console.log) There's really no major difference between those two constructs (well, promises also provide infrastructure for releasing to another control. All of those are synchronous functions, executed synchronously, in an asynchronous context, and all of them are called callbacks by what is perhaps the most authoritative source on web programming today.