I promised Nolan a response on why I didnt particularly agree with this post when I merged it, figure may as well here.
I think all the caveats applied to async function (ensure its inside a try/catch, dont use for in) points to how complicated it can be, http://jakearchibald.com/2014/es7-async-functions/ had to be amended with notes because a bunch of people very familiar with this style of coding still get it wrong. I cant see myself explaining to a new programmer how this all works.
I would really like to see us return to nice obvious blocking functions, taking the example the simplest way of all seems to be ...
let db = new PouchDB('mydb');
let result = db.post({});
let doc = db.get(result.id);
console.log(doc);
Let workers (or whatever equivalent they come up with in node) to make sure we dont block a single event loop and live happily ever after.
Basically copy erlang, but without actually having to use erlang.
Came to say the same. The more I think on this problem, the more I'm inclined to say promises aren't solving async well enough, and the only meaningful change would be what dale proposes - blocking functions in threads. This is what Bob Nystrom also concludes in a pretty compelling blog post, [1].
Some side notes - silent promise rejection is handled in io.js with the process 'unhandledRejection' event [2]. The difficulty with promises is that they can attach rejection handlers at any time, and so it's impossible to determine whether a rejection will never be handled. That's why the 'await' operator doesn't just throw if it's not inside a try/catch, and it's also why io.js includes the 'rejectionHandled' event [3], in case it turns out 'unhandledRejection' was emitted prematurely. Oh lord.
Also, keep in mind that ES7 is not standardized, so if you use a transpiler to get these new features, you're building on a bed of sand.
I agree that a purely blocking style would be best, and maybe we can hope for that in ES8. :) But async functions are still much nicer than promises.
And in practice, I don't think it will be that hard to explain to newbie programmers. Most of them will not be writing code that actually produces promises, just the code that consumes it (because they're not writing ajax/database libraries). So the "await" basically becomes part of the library API from their perspective.
E.g. they type "await library.doSomething()", their editor tells them that the surrounding function needs to be async, so they add the word "async," and they're done. They don't have to learn a completely new system in order to work with this library.
As for the uncaught Promise rejection project, it is certainly nasty (and has burned me many times as I worked on Pouch), but I'm hoping this can be solved by better tools. E.g. in Chrome, they recently started logging uncaught promise rejections to the console.
As a fan of go, I was also a bit disappointed at all the gotchas and how easy it is to make it wrong: if
let result = await db.post({});
works, why can't I
docs.forEach((doc) => await db.post(doc))
? I still have to keep promises somewhere in my head and work around them.
But I saw this post [0] the other day where the author reuses csp and go stuff and introduces them to js to basically achieve asynchronous actions in a synchronous manner:
function dbPost(doc) {
var ch = chan();
db.post(doc).then(function (res) {
csp.putAsync(ch, res);
})
return ch;
}
docs.forEach((doc) => yield csp.takeAsync(dbPost(doc)))
or, for your code:
go(function* () {
let db = new PouchDB('mydb');
let result = yield take(dbPost({}));
let doc = yield take(dbGet({}));
console.log(doc);
})
There still is some boilerplate compared to a fully synchronous code (and it introduces the notion of channels, which do have an added value other than just asynchronously waiting for a result), but overall I see it much more capable at the task than what is described in OP's article.
I think all the caveats applied to async function (ensure its inside a try/catch, dont use for in) points to how complicated it can be, http://jakearchibald.com/2014/es7-async-functions/ had to be amended with notes because a bunch of people very familiar with this style of coding still get it wrong. I cant see myself explaining to a new programmer how this all works.
I would really like to see us return to nice obvious blocking functions, taking the example the simplest way of all seems to be ...
Let workers (or whatever equivalent they come up with in node) to make sure we dont block a single event loop and live happily ever after.Basically copy erlang, but without actually having to use erlang.