To make code easy to read and maintain, we should follow some best practices.
In this article, we’ll look at some best practices we should follow to make everyone’s lives easier.
Replace the Use of the RegExp
Constructor in favor of Regular Expression Literals
Regex literals are much shorter than using the RegExp
constructor.
So we should use them in favor of the constructor.
For instance, instead of writing:
new RegExp("^\d.$");
We write:
/^\d.$"/
Using the Rest Parameters Instead of arguments
The argyments
object doesn’t work with arrow functions and it’s not an array.
Rest parameters return an array of the arguments.
So we should use that instead.
For instance, instead of writing:
function foo() {
console.log(arguments);
}
We write:
function foo(...args) {
console.log(args);
}
Use Spread Syntax Instead of .apply()
We should use the spread syntax instead of apply
.
For instance, instead of writing:
const args = [1, 2, 3, 100, 200\];
Math.max.apply(Math, args);
We write:
const args = [1, 2, 3, 100, 200];
Math.max(...args);
We don’t need apply
unless we want to change the value of this
.
Use Template Literals Instead of String Concatenation
We should use template literals instead of string concatenation.
It’s much easier to include expressions in template literals.
For instance, instead of writing:
const str = "hello, " + name + "!";
We write:
const str = `hello, ${name}!`;
Return Inside Each then()
to Create Readable and Reusable Promise Chains
We should return something if we want to call then
on the promise.
For instance, instead of writing:
myPromise.then(() => {
doSomething()
})
We write:
myPromise.then(() => {
return doSomething()
})
Use catch()
on Un-returned Promises
We should use catch
on unreturned promises to catch any errors to occur with them.
For instance, we can write:
myPromise
.then(doSomething)
.then(doMore)
.catch(errors)
where errors
is a callback to catch any error that occurred from the promises.
Make Sure to Create a Promise
Constructor Before Using it in an ES5 Environment
The Promise
constructor is introduced with ES6.
So any code written with older versions of ES must use a promise library to create promises.
For instance, instead of writing:
const x = Promise.resolve('foo');
We write:
const Promise = require('bluebird');
const x = Promise.resolve('foo');
No Nested then()
or catch() S
tatements
We should avoid nested then
or catch
statements.
For instance, instead of writing:
myPromise.then(val =>
doWork(val).then(doMore)
)
We write:
myPromise
.then(doWork)
.then(doMore)
.catch(errors)
Avoid Using new
on a Promise Static Method
If we are calling Promise
static methods, then we shouldn’; use the new
keyword.
For instance, instead of writing:
new Promise.resolve(value)
new Promise.reject(error)
new Promise.race([foo, bar])
new Promise.all([foo, bar])
We write:
Promise.resolve(value)
Promise.reject(error)
Promise.race([foo, bar])
Promise.all([foo, bar])
No return Statements in finally()
return
statements in finally
is useless since nothing will consume the result.
Therefore, instead of writing:
myPromise.finally((val) => {
return val
})
We write:
myPromise.finally((val) => {
console.log(val)
})
No Wrapping Values in Promise.resolve
or Promise.reject
when not Needed
We shouldn’t wrap values in Promise.resolve
or Promis.reject
when they aren’t needed.
For instance, instead of writing:
myPromise.then((val) => {
return Promise.resolve(val * 3);
})
myPromise.then((val) => {
return Promise.reject('foo');
})
We write:
myPromise.then((val) => {
return val * 3
})
myPromise.then((val) => {
throw 'foo'
})
return
will return a promise with the resolved value being the return value.
throw
will reject a promise with the given value.
Consistent Parameter Names when Creating New Promises
We should have consistent parameter names when creating new promises.
This way, there won’t be any confusion as to what they do.
For instance, instead of writing:
new Promise((reject, resolve) => { ... })
which have the functions in the wrong order or:
new Promise((ok, fail) => { ... })
which have nonstandard names, we write:
new Promise((resolve, reject) => { ... })
Prefer async/await to the Callback Pattern
async
and await
is shorter than the callback pattern, so we can sue that instead.
For instance, instead of writing:
myPromise
.then((val) => {
return foo();
})
.then((val) => {
return bar();
})
.then((val) => {
return val;
})
We write:
const foo = async () => {
const val1 = await myPromise;
const val2 = await foo();
const val3 = await bar();
return va3;
}
Conclusion
We should use spread and rest instead of apply
and arguments
.
Promises can be cleaned up in many ways.