News for hackers. Stuff that matters.
Re:Node v8.0.0 Released by nailer on Tuesday May 30, 2017 @03:24PM (#14447787)
Short ver: async await is now in an LTS release of node. Anything that returns a promise can now be run inline - ie, no endless .then() chaining - provided you've started an async context:

  const writeFile = util.promisify(fs.writeFile),
    request = util.promisify('superagent'),
    stat = util.promisify(fs.stat),
    sorts = require('sorts'),
    log = console.log.bind(console)

  const getJeansAndSaveThem = async function(){ 
    var jeans = await request.get('https://example.com/api/v1/product/trousers').query({
      label: 'Levi Strauss', 
      isInStock: true,
      maxResults: 500
    }).end()
    jeans = jeans.sort(sorts.alphabetical)
    await writeFile('jeans.json', jeans)
    const status = await stat('jeans.json');
    log(`I just got some data from an API and saved the results to a file. The file was born at ${status.birthtime}`)
  }
Note: you should add error handling, I'm new to async/await and this code is to demonstrate a concept on HN, not to run your life support system. ;-)
Re:Node v8.0.0 Released by flavio81 on Tuesday May 30, 2017 @03:42PM (#14447928)
As noted, this already was possible in Node 7.x. But to use it, you needed a function that returned a promise. And many functions do not, due to having been developed earlier. This is true even for libraries done in 2016. Even today many Node.js developers don't seem to use async/await. At least in my country... And thus they live in braces {} hell.

The improvement on the 8.0.0 version is that such an "oldie" function can be Promisified. A great improvement.

Re:Node v8.0.0 Released by floatboth on Tuesday May 30, 2017 @05:10PM (#14448575)
You could always promisify functions manually, or with this tiny package https://github.com/sindresorhus/pify but yeah it's nice to see that in the standard library.
Re:Node v8.0.0 Released by bfred_it on Tuesday May 30, 2017 @10:27PM (#14450069)
util.promisify is now in Node core as shown in the Original Comment
Re:Node v8.0.0 Released by simplify on Tuesday May 30, 2017 @03:50PM (#14448003)
By "oldie" function, do you mean functions that expect node-style callbacks?

  e.g. function myCallback (err, result) {...}
Re:Node v8.0.0 Released by styfle on Tuesday May 30, 2017 @03:58PM (#14448065)
Correct. Most node core APIs are written this way and now core ships an utility function[0] to wrap those functions in a promise.

[0]: https://medium.com/@styfle/promises-in-node-js-8-x-core-d6a8...

Re:Node v8.0.0 Released by mastax on Tuesday May 30, 2017 @05:39PM (#14448757)
It seems to me that Node should ship promisify-ed versions of all these functions (e.g. fs.readFileAsync). Over time they could replace the implementation with ones that use the OS Async APIs, though perhaps this step is unnecessary if you're already using an event loop underneath.
Re:Node v8.0.0 Released by lhnz on Tuesday May 30, 2017 @06:14PM (#14448982)
Until then you can use `mz` for a modernised API[0].

[0] https://github.com/normalize/mz

Re:Node v8.0.0 Released by NoInkling on Wednesday May 31, 2017 @02:21AM (#14450721)
I mean, they've been debating about how to add a promisified API for years (see for example https://github.com/nodejs/node/pull/5020) but nothing has come of it. util.promisify is a welcome addition, but very late for a first step.
Re:Node v8.0.0 Released by abalashov on Wednesday May 31, 2017 @08:28AM (#14451922)
How incredibly uncanny. Just yesterday morning, I posted this question!

https://stackoverflow.com/questions/44260289/using-native-es...

Re:Node v8.0.0 Released by mscdex on Tuesday May 30, 2017 @11:25PM (#14450226)
FWIW v8.0.0 is not an LTS release. Technically the first v8.x LTS release will happen in October. See this repo for more details: https://github.com/nodejs/lts
Re:Node v8.0.0 Released by Etzos on Tuesday May 30, 2017 @03:34PM (#14447870)
Async/await support (without the --harmony flag) was made default in version 7.6 when they updated V8 to version 5.5.

The biggest additions here with regard to async/await is the new promisify util and the async_hooks.

Edit: Changed wording and included more detail.

Re:Node v8.0.0 Released by nailer on Tuesday May 30, 2017 @03:43PM (#14447935)
Of course, but most people don't run non-LTS node releases :-)

Edit: originally wrote 'unstable'. Meant 'non-LTS'

Re:Node v8.0.0 Released by Etzos on Tuesday May 30, 2017 @03:49PM (#14447991)
The 7.6 release was no more unstable than the 8.0 release. Unless you're referring to the fact that 8.0 is going to be a LTS release. But if that's the case, it's not happening for a while yet, 6.10 is still the current LTS version.
Re:Node v8.0.0 Released by nailer on Tuesday May 30, 2017 @03:53PM (#14448022)
You're right, corrected.
Re:Node v8.0.0 Released by SparkyMcUnicorn on Tuesday May 30, 2017 @03:48PM (#14447980)
Node 7.6 is a stable release. Are you talking about LTS?
Re:Node v8.0.0 Released by NoInkling on Wednesday May 31, 2017 @02:24AM (#14450729)
And some performance improvements. And the fact that there are more to come when they upgrade to V8 5.9 soonish.
Re:Node v8.0.0 Released by kasbah on Tuesday May 30, 2017 @06:22PM (#14449029)
>request = util.promisify('superagent')

I don't think that's required. Superagent already returns promises.

Re:Node v8.0.0 Released by nailer on Wednesday May 31, 2017 @01:20AM (#14450576)
Ah you're right!

https://visionmedia.github.io/superagent/#promise-and-genera...

Alas too late to edit comment.

Re:Node v8.0.0 Released by candu on Wednesday May 31, 2017 @10:12AM (#14452650)
Sure, but having `util.promisify` in core modules means you no longer need an external dependency here.
Re:Node v8.0.0 Released by kasbah on Wednesday May 31, 2017 @02:04PM (#14454612)
Hm? It's not an external dependency. Superagent returns a promise.
Re:Node v8.0.0 Released by nailer on Wednesday May 31, 2017 @08:59AM (#14452094)
Replying to myself: since this comment is so popular, here's a fully working version for node 8:

  const util = require('util'),
    fs = require('fs'),
    writeFile = util.promisify(fs.writeFile),
    request = require('superagent'),
    stat = util.promisify(fs.stat),
    sorts = require('sorts'),
    log = console.log;

  const getPhotosAndSaveThem = async function(){
    try {
      const response = await request.get('https://jsonplaceholder.typicode.com/photos');
      const photos = response.body.sort(sorts.byKey('title'))
      await writeFile('photos.json', JSON.stringify(photos, null, 2))
      const status = await stat('photos.json');
      log(`I got some data from an API and saved the responses at ${status.birthtime}`)
    } catch (e) {
      log(`Oh no, something went wrong!`, e)
    }
  }

  getPhotosAndSaveThem()
Re:Node v8.0.0 Released by Rapzid on Tuesday May 30, 2017 @10:26PM (#14450063)
Is there a roadmap for supplying async/await interfaces for the entire stdlib? Still some event/callback based stuff in there that doesn't return promises or conform to the callback standard promisfy requires.
Re:Node v8.0.0 Released by peterparada on Tuesday May 30, 2017 @05:37PM (#14448747)
Yeah, most of the time, I need to handle errors with try/catch block.
Re:Node v8.0.0 Released by z3t4 on Wednesday May 31, 2017 @02:51PM (#14454955)
rant: why care about debugability and testability
Re:Node v8.0.0 Released by ujal on Tuesday May 30, 2017 @04:22PM (#14448238)
There should also be something like

  awaitAll 
to replace

  await Promise.all 
calls.
Re:Node v8.0.0 Released by adrusi on Tuesday May 30, 2017 @04:37PM (#14448335)
There are many ways to compose promises, no point in elevating some of them to keyword status. If you need to do anything interesting with promises, just use a promises library. The point of async/await is to free you from having to use callbacks, not to eliminate the need for libraries.
Re:Node v8.0.0 Released by ujal on Tuesday May 30, 2017 @04:52PM (#14448436)
Every async function will return a Promise anyway. I am simply interested in resolving a collection of Promises in a clean way.
Re:Node v8.0.0 Released by always_good on Tuesday May 30, 2017 @09:53PM (#14449959)
I don't see what's unclean about Promise.all or how creating a 1:1 alias for it makes it cleaner.

Also, many times you want to limit the concurrency of your promise execution which isn't something you can do with an array of promises. You'd be back to using `await` + something like https://www.npmjs.com/package/promise.map.

I'm someone that used to use `co` where you could go:

    const [a, b] = yield [promiseA(), promiseB()]
But I prefer the simplicity and consistency of having to use something like Promise.all or require('promise.map').
Re:Node v8.0.0 Released by ujal on Wednesday May 31, 2017 @05:36AM (#14451295)
Its the ambiguity for new programmers. With something like awaitAll new programmers wouldn't need to learn about Promises at all.

You have a point with concurrency, but handling concurrency is an another beast altogether.

Re:Node v8.0.0 Released by always_good on Wednesday May 31, 2017 @08:07AM (#14451807)
I have a hard time understanding how adding alias indirection disambiguates anything much less spares one from learning something.

How does one get to the point where they want to await multiple promises, yet they need to be insulated from the very presence of the `Promise` object?

Re:Node v8.0.0 Released by ujal on Wednesday May 31, 2017 @09:29AM (#14452300)
Well at least in my mental model a Promise is an object that eventually resolves to something within its .then() method. In contrast my mental model of await is that of a blocking call. One can internalize the latter without the former.
Re:Node v8.0.0 Released by abritinthebay on Tuesday May 30, 2017 @07:41PM (#14449462)
Given Promise.all resolves to an ordered array surely this would work:

    const [foo, bar, baz] = await returnerOfPromiseCollection();
That would assume there was either a) a catch in that collect or b) some error checking, but still...
Re:Node v8.0.0 Released by bfred_it on Tuesday May 30, 2017 @10:32PM (#14450087)
It "works" but foo won't contain the resolved value, just the promise.

The code is awaiting an array, which is already "resolved" and its returned right away. Its contents are not relevant to `await`.

Re:Node v8.0.0 Released by abritinthebay on Wednesday May 31, 2017 @01:50AM (#14450642)
You are correct! My apologies = I misremembered how that works >_<

Yes, once you have a promise you have to deal with it as such through the whole chain.

Re:Node v8.0.0 Released by bfred_it on Tuesday May 30, 2017 @10:40PM (#14450099)
Promise.all is not even that good. If one fails, the rest of the Promises are lost. It does not wait for all Promises.

I prefer something like p-settle most of the time https://github.com/sindresorhus/p-settle

Re:Node v8.0.0 Released by Ajedi32 on Tuesday May 30, 2017 @04:56PM (#14448470)
Pretty sure there used to be a syntax in the spec for handling that. Something like `await*` I believe. It got removed pretty early on in the process though.
Re:Node v8.0.0 Released by ujal on Wednesday May 31, 2017 @06:30AM (#14451461)
Any interesting reasons as to why?
Re:Node v8.0.0 Released by Ajedi32 on Wednesday May 31, 2017 @09:15AM (#14452202)
I wasn't really involved in those discussions, but I suspect it's for similar reasons to what others in the comments here are arguing; they wanted to keep the syntax minimal and decided that adding a special syntactic sugar for something that could already be accomplished by `Promise.all(...)` was unnecessary.
Re:Node v8.0.0 Released by steve_adams_86 on Tuesday May 30, 2017 @04:23PM (#14448243)
You can make it yourself fairly easily I guess:

    const awaitAll = Promise.all.bind(Promise);

    async function foo() {
        var [val1, val2] = await awaitAll([func1, func1]);
    }
It isn't ideal but it's a little cleaner
Re:Node v8.0.0 Released by nailer on Tuesday May 30, 2017 @04:57PM (#14448478)
+1. I'm a big fan of top level function binds to remove boilerplate and keep code readable:

  const log = console.log.bind(console), 
    query = document.querySelector.bind(document),
    queryAll = document.querySelectorAll.bind(document);
Re:Node v8.0.0 Released by RReverser on Tuesday May 30, 2017 @08:10PM (#14449599)
You don't need to bind `console.log` by the way (at least not in any recent version of Node.js or browsers).
Re:Node v8.0.0 Released by ujal on Tuesday May 30, 2017 @04:58PM (#14448485)

  await all([fn1, fn2]) ;)
i wonder when we will get s-expressions for function calls

  (awaitAll [fn1, fn2])
Re:Node v8.0.0 Released by doublerebel on Tuesday May 30, 2017 @06:44PM (#14449167)
Just write (iced) coffeescript, s-exp are totally valid there:

https://github.com/nextorigin/riemann-query-parser/blob/mast...

Re:Node v8.0.0 Released by ujal on Tuesday May 30, 2017 @06:53PM (#14449226)
Yeah, s-exps are the only thing I miss :(
Re:Node v8.0.0 Released by krisdol on Tuesday May 30, 2017 @06:28PM (#14449071)
You can use .map to call await on every element in the array, or define a new function so you don't have to write that all the time:

    const awaitAll = (futures) => futures.map(f => await f);
edit: this is wrong but I can't delete it. Haven't used async as much as promises.
Re:Node v8.0.0 Released by ujal on Tuesday May 30, 2017 @06:38PM (#14449131)
Well an async function always returns a Promise. await simply blocks until the Promise is resolved to continue execution. Thats why I am wondering why they decided to await only on a single Promise.
Re:Node v8.0.0 Released by ujal on Tuesday May 30, 2017 @06:30PM (#14449083)
Don't you need to be in an async context to call await?
Re:Node v8.0.0 Released by AngelloPozo on Tuesday May 30, 2017 @03:32PM (#14447858)
Async await being part of core, not behind a flag, is probably my favorite new addition.
Re:Node v8.0.0 Released by partycoder on Tuesday May 30, 2017 @04:50PM (#14448425)
1) This was possible in node 7

2) A request can fail and can timeout.

3) Writing to a file can fail.

And you get the idea. Don't omit error handling. Error handling is business logic too.

Being relaxed around error handling is the recipe for cascading server failure.

Re:Node v8.0.0 Released by nailer on Tuesday May 30, 2017 @05:02PM (#14448516)
I'm just getting started with async/await (like most people I stick to LTS releases) so please forgive the lack of error handling in the demo code!
Re:Node v8.0.0 Released by kabes on Wednesday May 31, 2017 @04:15AM (#14451049)
Note that node 8.0.0 is not LTS. Node 8.x will be an LTS release around October.
Re:Node v8.0.0 Released by partycoder on Tuesday May 30, 2017 @05:07PM (#14448548)
As someone who spends all day volunteering in Stack Overflow I hope people providing examples were a little bit better at emphasizing error handling.

You should see the destructive effects of bad examples there.

Re:Node v8.0.0 Released by nailer on Tuesday May 30, 2017 @05:09PM (#14448573)
You're welcome to add it.
Re:Node v8.0.0 Released by danneu on Wednesday May 31, 2017 @01:58AM (#14450665)
In their snippet, errors would be handled altogether on the promise you get from `getJeansAndSaveThem()`.

You don't have enough information to be outraged at the toy example.

Re:Node v8.0.0 Released by partycoder on Wednesday May 31, 2017 @04:00AM (#14451006)
And that's a very implicit way of handling the error. Implicit behavior is good when you are encapsulating stuff (e.g: I don't need to know about the details of internal combustion engines, just pushing on the accelerator of my car so it moves forward).

But in this case encapsulation is a leaky abstraction that just makes the diagnosing of an error more cumbersome.

Re:Node v8.0.0 Released by ryeguy on Tuesday May 30, 2017 @09:53PM (#14449958)
Oh please. The point of the post was to illustrate the feature to those wondering "what's async/await?", error handling would be complete noise for that purpose.
Re:Node v8.0.0 Released by partycoder on Wednesday May 31, 2017 @03:46AM (#14450976)
I would argue with you, but I don't really have to prove you wrong.

You will eventually prove yourself wrong, since deemphasizing error handling goes wrong very quickly.

Re:Node v8.0.0 Released by minitech on Tuesday May 30, 2017 @08:52PM (#14449772)
One of the nice things is that you can just let async functions fail and they won’t throw asynchronously and kill the process. So no, error handling isn’t important to include in a small example.
Re:Node v8.0.0 Released by NoInkling on Wednesday May 31, 2017 @02:33AM (#14450751)
Previously that characteristic was also a massive pain point for debugging Node apps though - neglecting error handling would result in silently swallowed errors and leave people (particularly newbies) scratching their heads.

Then they added unhandled rejection warnings by default, and all was ok again - but I see why someone might insist that all examples have error handling.

Re:Node v8.0.0 Released by minitech on Wednesday May 31, 2017 @10:56PM (#14457663)
That’s not something that should be handled inside an async function (and therefore not in this example). If you don’t want to continue a promise chain, terminate it:

  .catch(error => {
    process.nextTick(() => { throw error; });
  })
Re:Node v8.0.0 Released by partycoder on Thursday June 01, 2017 @01:22AM (#14458181)
You want to use setImmediate rather than process.nextTick.
Re:Node v8.0.0 Released by minitech on Thursday June 01, 2017 @09:37PM (#14466782)
Mmm… no, I didn’t want to. Why do you say that?
Re:Node v8.0.0 Released by Noseshine on Wednesday May 31, 2017 @08:33AM (#14451954)
Obviously the example code is inside another function - `await` can only be used inside a function marked with `async`, which always returns a promise.

That means error handling may not be necessary inside that function. Errors are caught automatically and returned to the caller as rejected promise! You need error handling at the top level but not necessarily inside each function.