5

I'm quite new to async/await and would like to know, what is the best way to refactor the below code with async/await?

export const createUser = (values, history) => {
  return dispatch => {
    axios.post('/api/signup', values)
      .then(res => {
        console.log('result', res);
      }, rej => {
        console.log('rejection', rej);
      });
  }
}

When only one argument is provided to .then it is pretty straightforward to me, but what happens if you have two arguments like here instead?

doctopus
  • 5,349
  • 8
  • 53
  • 105
  • 2
    You might simply want to [not change it at all](https://stackoverflow.com/a/44664037/1048572) when `await` doesn't improve clarity. – Bergi Oct 15 '17 at 21:51
  • The other problem here is that the function does not return anything so the caller can't know when the `axios.post()` is done and/or if there's an error. You should be returning the promise and your reject handler needs to propagate the error too and your success handler needs to return the value. – jfriend00 Oct 15 '17 at 22:38

2 Answers2

4

Here's how to do it, using https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function as a reference:

 const f = (values, history) => {
    return async function createUser( dispatch ) {
        try {
           const res = await axios.post('/api/signup', values);
           console.log('result', res);
        } catch(e) {
           console.log('reject', e);
        }         
    };
 }
Duncan Thacker
  • 5,073
  • 1
  • 10
  • 20
3

The two arguments to .then are just the success and error callbacks. You could also write this as .then(res => {}).catch(rej => {})

Essentially you can think of the result of await as a .then callback. Any time you're waiting for the result of a promise, whether or not you use it, use await. For any errors, use the usual try/catch.

return async () => {
  try {
    const res = await axios.post('/api/signup', values);
    console.log('result', res);
  }
  catch (rej) {
    console.log('rejection', rej);
  }
}

One thing to keep in mind is that async functions always return a Promise, so the calling code has to be written to account for that.

I wrote a blog post about async/await (disclaimer, yes I wrote this).1

Marco Talento
  • 2,335
  • 2
  • 19
  • 31
Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • 2
    No, you can't really, there's a [difference between `.then(…, …)` and `.then(…).catch(…)`](https://stackoverflow.com/q/24662289/1048572) which might be important. – Bergi Oct 15 '17 at 21:52
  • @Bergi Thanks for pointing that out. In this specific case I don't think it would matter since `console.log` would not fail, but knowledge of this distinction is important. – Explosion Pills Oct 15 '17 at 21:54
  • I wouldn't be so sure of that. Maybe it might throw when there's something wrong with the stdout stream it writes to? Maybe someone even messed with the `console` global object? Or a less contrived example (that I've actually seen happening in the wild) would be an exception from the stringification of `res`. – Bergi Oct 15 '17 at 22:04
  • 3
    Add `await` before `axios.post(...)` call, because currently your example is absolutely wrong. – alexmac Oct 15 '17 at 22:28
  • @alexmac Thanks I missed the most important part! – Explosion Pills Oct 16 '17 at 01:48
  • @Bergi in this case if the console.log for result also fails it would still be caught. How would you rewrite this to adapt it to having an error handler for .then? – Explosion Pills Oct 16 '17 at 01:51