Promise provides an impressive way to handle exceptions. Exception handling in promise is quite simple and easy to implement, and almost all libraries and implementations support a generic way of implementation. Here are some of best practices to deal with exceptions:
To maximize performance and maintainability, throw understandable errors. The best practice is to reject a promise and reject it with an error instance. Make it a habit not to reject an error object or primitive values.
Keep an eye on the effects of errors on the flow of execution. The best practice for doing this is to anticipate failures in your handlers. The better you are at anticipation, the better will be your control over the flow of execution. Always think whether your rejection handler should be invoked by failures in the resolution handler, or if there should be a different behavior.