14

I am working on redux-form atm and found the piece of code. Its working for me but is there any cleaner way to write this in ES6 style?

const asyncValidate = (values/* , dispatch */) => {
  return new Promise((resolve, reject) => {
    try {
      if (['john', 'paul', 'george', 'ringo'].includes(values.name)) {
        const error = {
          name: 'That username is taken'
        };
        throw error;
      }
      resolve();
    } catch (e) {
      reject(e);
    }
  });
};

I would appreciate your help


Solution

const asyncValidate = (values/* , dispatch */) => {
  return new Promise((resolve, reject) => {
    const errors = {};
    if (['john', 'paul', 'george', 'ringo'].includes(values.name)) {
      errors.name = 'That username is taken';
    }
    reject(errors);
  });
};

probably cleaner way?!

tomole
  • 927
  • 3
  • 12
  • 35

2 Answers2

42

try/catch is redundant in promise chains and promise executor functions.

Any error thrown is automatically converted to a rejection of the promise you're supposed to return. The promise code calling your function takes care of this. So just do:

const asyncValidate = values => new Promise(resolve => {
  if (['john', 'paul', 'george', 'ringo'].includes(values.name)) {
    throw { name: 'That username is taken'};
  }
  resolve();
});

and it gets converted to a rejection.

jib
  • 40,579
  • 17
  • 100
  • 158
  • 3
    good explanation! Any unhandled exception inside a promise constructor is automatically wrapped inside a rejected promise. This is also true for the newly created promises inside a then() which makes it easy to just use throw() inside. (see [25.4.1.3.2 in ES6 spec](http://www.ecma-international.org/ecma-262/6.0/#sec-promise-resolve-functions)) – opt12 Jan 18 '17 at 14:22
0

You can use Conditional (ternary) Operator to simplify if-statement, also you don't need a catch block here:

//ES5
const asyncValidate = (values) => {
    return new Promise((resolve, reject) => {
        ['john', 'paul', 'george', 'ringo'].includes(values.name) ? reject({ name: 'That username is taken' }) : resolve();
    });
};

//ES6 - using "generators"
const asyncValidate = function* (values) {
    return yield ['john', 'paul', 'george', 'ringo'].includes(values.name) ? Promise.reject('That username is taken') : Promise.resolve();
}
Shaharyar
  • 12,254
  • 4
  • 46
  • 66
  • This doesnt work for me: "Uncaught Error: asyncValidate function passed to reduxForm must return a promise" – tomole Jan 11 '17 at 22:49
  • Returning a generator of promises is not the same as returning a promise?! Maybe what you meant was an ES8 `async function`. – Bergi Jan 12 '17 at 01:05