3

I have being using Promises for a long time, and they are always the "thing" that I use to control the workflow of my programs. Example:

Promise
  .resolve(obj)
  .then(doSomething1)
  .then(doSomething2)
  .catch(handleError)

And now, I would like to change to a try-catch style, but I don't know exactly what would be the right approach.

V1:

try {
  var body = await Promise
               .resolve(obj)
               .then(doSomething1)
               .then(doSomething2)
} catch (error) {
  callback(error)
}
callback(null, {
  statusCode: 200,
  body
})

V2:

try {
  var body = await Promise
               .resolve(obj)
               .then(doSomething1)
               .then(doSomething2)
               .then(body => {
                 callback(null, {
                   statusCode: 200,
                   body
                 })
               })
} catch (error) {
  callback(error)
}

What would be the right approach?

FXux
  • 415
  • 6
  • 15
  • I don't think there is a right approach in this case. It depends on what's most maintainable. – Austin Brunkhorst Dec 22 '17 at 01:26
  • Kind of an opinion based question, but I like V1 more. Better to have the `callback` invocations close to each other, rather than one in a `.then` and the other in the `catch` block. But my favorite snippet is actually the very first one that uses promises only. – CRice Dec 22 '17 at 01:27
  • I don't see why you would want to change to a `try` in the first place? – Ry- Dec 22 '17 at 01:40
  • In any case, you would *not* invoke a callback but rather return the resolve a returned promise. – Bergi Dec 22 '17 at 02:04
  • Your V1 does not work. In case of an error, the `callback` is invoked twice. – Bergi Dec 22 '17 at 02:05
  • I resisted async/await until Node 8. After using it for a few months I am glad I switched. The big payoff is mixing async and sync code together. You pretty much never employ Promise.resolve(...) like in your example. It's just a lot cleaner and more readable. – john_omalley Dec 26 '17 at 17:48

1 Answers1

5

You don't have to use a callback function in order to switch to async/await. An async function is just a Promise-returning function, and await is there as a convenience. So the equivalent of your original function is simply:

async function fn() {
  try { 
    const obj = ...;
    const result1 = await doSomething1(obj);
    const result2 = await doSomething2(result1);
    return result2;
  } catch (err) {
    return handleError(err);
  }
}

If you do want that callback:

async function fn(callback) {
  try { 
    const obj = ...;
    const result1 = await doSomething1(obj);
    const result2 = await doSomething2(result1);
    callback(null, result2);
  } catch (err) {
    callback(err);
  }
}
Jacob
  • 77,566
  • 24
  • 149
  • 228
  • 1
    [Do not forget](https://stackoverflow.com/a/43985067/1048572) to `await` the `doSomething2()` call in your first snippet – Bergi Dec 22 '17 at 02:03
  • Any return is wrapped in a `Promise.resolve`. Returning a Promise is the same as awaiting said promise and then returning the result, so it's a handy shortcut just returning the final promise. – Jacob Dec 22 '17 at 17:30