The way I handle situations like this is to only put the catches where I need them to serve some purpose. Generally, I don't catch errors at the start of the chain because I can't know what to do with them at that point. If I do catch them, it's only for logging or similar purposes and I still let the error propagate further.
Another pattern I use is to split the promise chain so that I let my main results flow be the result that gets passed on, but I can do other things in a parallel manner internally:
One pattern I use is to rethrow the error:
return service.fetchData().then((data) => {}).catch((err) => {console.log(err); throw err;});
Another pattern I use is to split the promise chain so that I let my main results flow be the result that gets passed on, but I can do other things in a parallel manner internally:
let results = service.fetchData().then((data) => {}); results.catch((err) => {console.log(err);}); return results;