Javascript uncaugh error in promise even with a catch

794 Views Asked by At

With Javascript, I am trying to make a call to an external API when a form is submited. I am using promises in order to set follow up actions once the call is done and to catch eventual errors.

This is where my problem is, even if I think I am catching my errors correctly, the console throws an

Uncaught (in promise) error : [The error I throw]

I do not understand why.

Here is a minimal version of my code which would reproduce the error when the refreshToken is expired :

try {
        functionGeneratingTheError();
    } catch (error) {
        doSomethingElse();
    }
function functionGeneratingTheError() {
    
    var getTokenCallPayload = {
        "client_id" : clientId,
        "client_secret" : clientSecret,
        "refresh_token" : refreshToken,
        "grant_type" : "refresh_token"
    };
    var getTokenCallOptions = {
        "method" : "POST",
        "body" : JSON.stringify(getTokenCallPayload),
        "muteHttpExceptions" : false
    };
    fetch(tokenURL, getTokenCallOptions)
    .then(response => {
        if (response.ok) {
            return response.json();
        } else {
            throw new Error("Error");
        }
    })
    .then(data => {
        doSomething();
    })  
    .then(response=> {
        doSomethingAgain();
    }) 
    .catch(error => {
        throw error;
    });
}

If I understand correctly, when the fetch is a bad request, it should throw the error "Error" which should then be caught in the first catch and run the doSomethingElse() function. However, instead of doing that, I get this error in the browser console "Uncaught (in promise) Error: Error"

What am I doing wrong ?

I have tried including the fetch in a try{}catch(){} but it doesn't change anything.

I also tried not throwing the error and directly call my doSomethingElse() function, but then the following .then fails because data is undefined.

1

There are 1 best solutions below

4
Kagiso Marvin Molekwa On BEST ANSWER

Change your functionGeneratingTheError function to return the chained promise like below:

function functionGeneratingTheError() {
    
    var getTokenCallPayload = {
        "client_id" : clientId,
        "client_secret" : clientSecret,
        "refresh_token" : refreshToken,
        "grant_type" : "refresh_token"
    };
    var getTokenCallOptions = {
        "method" : "POST",
        "body" : JSON.stringify(getTokenCallPayload),
        "muteHttpExceptions" : false
    };

    return
    fetch(tokenURL, getTokenCallOptions)
    .then(response => {
        if (response.ok) {
            return response.json();
        } else {
            throw new Error("Error");
        }
    })
    .then(data => {
        doSomething();
    })  
    .then(response=> {
        doSomethingAgain();
    }) 
    .catch(error => {
        throw error;
    });
}

And then await it in your calling code by wrapping the calling code inside an async self invoking function like so:

(async function() {
try {
        await functionGeneratingTheError();
    } catch (error) {
        doSomethingElse();
    }
})();

You can read more about async/await here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function