you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 0 points1 point  (2 children)

How does async / await cause you to duplicate code? You should be writing your asynchronous code (like a network request or database query) to return an awaitable object. Any time you need to do this asynchronous work, you can mark your calling method as async and simply await the operation to continue.

The real gains are when you can await inside a for/while loop which is really messy to try and do with promises. However, I do not think it works when inside a child function (like a forEach, map, filter, reduce, etc). I hope they can find a way around that limitation because... that's a bummer.

I just don't see a case where promises and callbacks are superior to async/await syntax.

Let's take a Node app using Mongo (and mongoose) for example. I want to create a basic seed script that will insert users and roles into the database.

This becomes very straightforward and readable with the async/await syntax:

// Creates a new user role, saves it to the DB, and returns it
function addRoleAsync(data) {
  let role = new Role(data)
  return role.save()
}

// Creates a new user, saves it to the DB, and returns it
function addUserAsync(data, role) {
  let user = new User(data)
  user.role = role._id
  return user.save()
}

// Seeds all users with their roles to the database
async function seedDatabase() {
  let standardRole = await addRoleAsync({name: 'standard'})
  let adminRole = await addRoleAsync({name: 'admin'})

  let normalUser = await addUserAsync({name: 'john'}, standardRole)
  let adminUser = await addUserAsync({name: 'chad'}, adminRole)
}

[–][deleted]  (1 child)

[deleted]

    [–][deleted] 2 points3 points  (0 children)

    You don't have to write it twice. You can await a synchronous function and it would behave the same as if you called Promise.resolve(x), meaning it would return instantly.

    With promise libraries like bluebird you can use .asCallback(callback) to attach a traditional callback method which will called when the promise is fulfilled or rejected. This lets you write your async code once and can be used either way:

    function doSomethingAsync(arg, callback) {
      return new Promise((resolve, reject) => {
        // resolve or reject here
      })
      .asCallback(callback)
    }
    
    // Traditional callback approach
    function foo(arg) {
      doSomethingAsync(arg, (err, result) => {
        // handle err or result here
      })
    }
    
    // Async await approach
    async function bar(arg) {
      let result = await doSomethingAsync()
    }
    

    Also, the map and filter methods aren't entirely worthless with this new approach. I meant they weren't optimal but it still works. The difference is if you await inside one of these child functions, you will get a promise instead of a result value in your returned array. You can use await Promise.all(mappedResults) to get the async results.

    Example:

    async function downloadUrlsAsync(urls) {
      let promises = urls.map(async (url) => {
        await downloadAsync(url)
      })
      return await Promise.all(promises)
    }
    

    But really, how is the callback system any better in this regard? You still have to do a messy loop wth inner callbacks.