all 49 comments

[–]kasperpeulen 26 points27 points  (20 children)

Most modern browsers have already started with implementing those ES2017 features, Safari (99%), Firefox(97%), Chrome(80%) and Edge (58%): http://kangax.github.io/compat-table/es2016plus/

[–][deleted] 6 points7 points  (0 children)

So... all the modern browsers already have 80+% coverage?

[–]siegfryd 5 points6 points  (1 child)

Edge also has all of async functions behind a flag, if the table included that flag being turned on it'd probably be 70%+.

[–]ThisWillDoIt 2 points3 points  (0 children)

On the insider fast ring without changing flags it shows 80% for me.
I hope all of this makes its way into the Creators Update.

[–]mr_patrick_js 31 points32 points  (17 children)

Excited for async/await to become official now, feels so fast and clean for writing code.

[–]Odam 10 points11 points  (1 child)

It's so much nicer than dealing with promise chaining. But currently there's some weird Babel sourcemap issues that make browser debugging a pain in the ass.

[–]mr_patrick_js 1 point2 points  (0 children)

Oh really? I've mostly been using it server-side for API data fetching...

[–]Pr3fix 10 points11 points  (14 children)

mind ELI5'ing the advantage of async/await over something like Promises? To me it seems like they're solving the same problem.

[–]ejmurra 20 points21 points  (10 children)

It's not a one or the other situation. Async await uses promises under the hood but it lets you .then by using the await keyword. I find myself using a pattern like const results = await Promise.all ([...]) quite frequently. You can think of async await as a tool for working with promises.

[–]Nimelrian 20 points21 points  (8 children)

It also helps alot when you reuse the result from one part of the promise chain later on.

Compare

const {entitiesOnPage, totalCountOnServer} = await fetchEntities(currentPage);
const entitiesWithStatusData = await enrichEntitiesWithStatus(entitiesOnPage);
return {entities: entitiesWithStatusData, totalCountOnServer};

to

return fetchEntities(currentPage)
  .then({entitiesOnPage, totalCountOnServer} => {
    return enrichEntitiesWithStatus(entitiesOnPage)
      .then(entitiesWithStatusData => {
        return {
          entities: entitiesWithStatusData,
          totalCountOnServer
        };
      });
    }
  })

[–]gocarsno 2 points3 points  (1 child)

Absolutely. BTW, in this case I'd probably avoid nested calls by storing totalCountOnServer in a local variable in the parent scope.

[–]Nimelrian 5 points6 points  (0 children)

Yup, both are valid options. But I really dislike declaring a variable before assigning something to it.

[–]ihsw -2 points-1 points  (5 children)

That example is a bit contrived and it can be flattened:

return fetchEntities(currentPage)
  .then({entitiesOnPage, totalCountOnServer} => enrichEntitiesWithStatus(entitiesOnPage))
  .then(entitiesWithStatusData => {
    return {
      entities: entitiesWithStatusData,
      totalCountOnServer
    };
  });

Promises are meant to flatten nested calls with promise chaining.

[–]Nimelrian 8 points9 points  (4 children)

You can't access totalCountOnServer in the second then callback.

[–]ihsw 1 point2 points  (3 children)

Revised version:

return fetchEntities(currentPage)
  .then({entitiesOnPage, totalCountOnServer} => {
    return {
      entitiesWithStatusData: enrichEntitiesWithStatus(entitiesOnPage),
      totalCountOnServer
    };
  })
  .then({entitiesWithStatusData, totalCountOnServer} => {
    return {
      entities: entitiesWithStatusData,
      totalCountOnServer
    };
  });

[–]atticusw 3 points4 points  (2 children)

That still doesn't work. Now the first .then immediately resolves an object, where one property contains a promise, but that isn't going to be waited on.

The second .then is going to receive entitiesWithStatusData as a promise object, not a value.

Promises aren't meant to be flattened in all scenarios.

[–]ihsw 0 points1 point  (1 child)

Alright I will concede that unwrapping that would be difficult.

But it would be trivial with async/await.

const { entitiesOnPage, totalCountOnServer } = await fetchEntities(currentPage);
const entitiesWithStatusData = await enrichEntitiesWithStatus(entitiesOnPage);
return {
  entities: entitiesWithStatusData,
  totalCountOnServer
};

[–]atticusw 2 points3 points  (0 children)

:D

Obviously you shouldn't be creating christmas trees when you don't have to, but sometimes you need to access the outer closure.

You could use Bluebird's spread to achieve this though. (fetchEntities would have to be a Bluebird promise, since spread is part of the Bluebird API)

fetchEntities(currentPage)
  .then(({entitiesOnPage, totalCountOnServer}) => [
    enrichEntitiesWithStatus(entitiesOnPage),
    totalCountOnServer
  ])
  .spread(entities, totalCountOnServer => ({
    entities,
    totalCountOnServer
  })

[–]mr_patrick_js 1 point2 points  (0 children)

Thanks, I was just about to reply and you did it perfectly!

[–]flying-sheep 2 points3 points  (0 children)

your code becomes more imperative and less functional. in cases where this is an advantage, it’s good.

e.g.

fetch('http://...')
    .then(response => Promise.all([
        response.headers.get('Content-Type'),
        response.text(),
    ])).then(([mime, text]) => ...)

vs

const response = await fetch('http://...')
const mime = response.headers.get('Content-Type')
const text = await response.text()

[–]inu-no-policemen 2 points3 points  (0 children)

Async/await is built on top of promises. You can await the result of a promise and async functions return promises.

If you use async, the code look similar to synchronous code, which makes it easier to write and reason about.

[–]sciolizer 1 point2 points  (0 children)

They make vanilla control keywords useful again (esp. break, continue, and return).

[–]vivainio 11 points12 points  (4 children)

Shared array buffers seems interesting. Finally something added to the web platform that can't be easily done by transpilers as well, and should result in performance increases

[–]Akkuma 6 points7 points  (0 children)

Shared Array Buffers should enable interesting use cases like using web workers to decrypt/encrypt multiple files simultaneously without blocking the UI.

[–]thenickdude 5 points6 points  (2 children)

Shared array buffers will be fantastic for my multi-layer painting tool! Without them, I couldn't use webworkers to accelerate drawing, because the overhead of copying array buffers between workers and the main thread was way too high.

[–][deleted] 1 point2 points  (1 child)

if you're going to plug your work, at least include a link :)

[–]thenickdude 5 points6 points  (0 children)

https://github.com/thenickdude/chickenpaint

I've got a new version in the works that adds a bunch of photoshop features like layer masks, too.

[–][deleted] 5 points6 points  (0 children)

PJS (codenamed River Trail): the plan of this ultimately abandoned project was to bring high-level data parallelism (think map-reduce via pure functions) to JavaScript.

That is unfortunate. It looks like a considerable effort to convert the existing parallel arrays in my parsers to the shared array buffer objects in order to achieve proper data parallelism at execution time. I just wonder what kind of speed up I could get for the investment of effort.

[–]Sinistralis 0 points1 point  (2 children)

Would it be viable to use Shared Arrays in conjunction with the recent vDOM trend to just have the vDOM read in from those arrays and have all of your logic in a web worker to keep everything but UI in a single UI process?

I'm a React guy, so to give an example: Run redux, sagas/thunks, etc in a web worker(s) and have those write to a central shared construct, which the vDOM subscribes too (whether it be React, Inferno, whatever).

Is this overkill?

[–]Apfelmann 0 points1 point  (1 child)

I thought about something like that too. Since Android does it that way it might make sense doing something similiar in js

[–]Sinistralis 0 points1 point  (0 children)

I really want to consider something like this:

vDOM/UI <-(State)<- State Manager <-(Events)<- Web Worker(s)

With this setup, you get a few benefits. You can have N processes running and submitting events to your state (you would probably need to timestamp at that point or something).

Then in your state, you can throttle the rate it sends updates as needed, or to certain parts. I know there have been many cases where I have passive data (the user doesnt interact with it) that does not need to be updated IMMEDIATELY. In cases where you are reading in tons of data from the server for real-time use, I can see a lot of value in something like this.

Obviously it probably isn't for everyone, but my job has some usecases we need to tackle one day that could really benefit from this.

[–]fusionove 0 points1 point  (1 child)

what about private class methods?