1

I'm wondering if it's possible to refactor multiple identical catch blocks into a single catch block when working with promise chains in es2015.

See the following promise chain (doesn't matter what it does):

replace(replaceOptions(dirPath + '/' + jsName))
         .then((changes) => {
             fileModifiedPrint(changes);
             removeDocumentation(jsName, dirPath, dirName);
             replace(replaceHTMLID(dirPath + '/' + jsName))
                .then((changes) => {

                })
                .catch((err) => {
                    fileErrorPrint(jsName, dirPath, err, "write"); return;
                })
         })
         .catch((err) => {
             fileErrorPrint(jsName, dirPath, err, "write"); return;
         })

Can I combine these two catch blocks into one?

JavascriptLoser
  • 1,853
  • 5
  • 34
  • 61
  • I believe so, errors bubble out to the outer catch statements – Varinder Feb 14 '18 at 01:30
  • 3
    You should be chaining promises (`return replace(…`, for example, always, for every promise). See https://stackoverflow.com/questions/22539815/arent-promises-just-callbacks – Ry- Feb 14 '18 at 01:31

2 Answers2

3

Is it possible to combine multiple identical catch blocks?

Yes, you can if you chain your promises by returning the inner promise from within the .then() handler and then let reject propagation bubble up to a single .catch() block:

replace(replaceOptions(dirPath + '/' + jsName)).then((changes) => {
    fileModifiedPrint(changes);
    removeDocumentation(jsName, dirPath, dirName);

    // return this promise to chain it to the parent promise
    return replace(replaceHTMLID(dirPath + '/' + jsName)).then((changes) => {
        // do whatever you want here
    });
}).catch((err) => {
    // this will catch any rejection anywhere in the promise chain
    // that wasn't already caught by someone
    fileErrorPrint(jsName, dirPath, err, "write");
});

When you chain promises, a rejected promise will propagate back up to the chain to the first .catch() handler in the chain that it encounters. If there is no .catch() handler until the top level, then it will go all the way up to that .catch(). This allows you to either handle a rejection locally and "hide" it from the rest of the chain or to let it reject the whole chain by letting it propagate up. You can implement either type of logic depending upon what is most appropriate for your particular situation.


FYI, you can also un-nest your .then() on the inner replace() too like this:

replace(replaceOptions(dirPath + '/' + jsName)).then((changes) => {
    fileModifiedPrint(changes);
    removeDocumentation(jsName, dirPath, dirName);

    // return this promise to chain it to the parent promise
    return replace(replaceHTMLID(dirPath + '/' + jsName));
}).then((changes) => {
    // results of the second `replace()` call.
    // do whatever you want here
}).catch((err) => {
    // this will catch any rejection anywhere in the promise chain
    // that wasn't already caught by someone
    fileErrorPrint(jsName, dirPath, err, "write");
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
-2

sort of.

When you call .catch((err) => { /*error catching*/ }), you are specifying a callback function that will be called if an error occurred. Because you are using the same code to catch the errors, you can make a function and pass it to catch instead:

const errorCallback = function(err) { fileErrorPrint(jsName, dirPath, err, "write"); }

replace(replaceOptions(dirPath + '/' + jsName))
         .then((changes) => {
             fileModifiedPrint(changes);
             removeDocumentation(jsName, dirPath, dirName);
             replace(replaceHTMLID(dirPath + '/' + jsName))
                .then((changes) => {

                })
                .catch(errorCallback);
         })
         .catch(errorCallback);
obwan02
  • 113
  • 10