Search code examples
javascriptnode.jsparse-platform

Why does this promise not go to the next "then"?


So I have this code:

Parse.Cloud.define("apiCall", function(request, response) {

    return Parse.Cloud.httpRequest({
        // API call 1
    }).catch(function(error) {
        /// Only perform this if the first call fails

        // Return valid json here, to mock the Parse.Cloud.httpRequest below
        return Parse.Promise.as({"data": "this is an expected JSON"});

        return Parse.Cloud.httpRequest({
            // API call 2
        });
    }).then(
        function(httpResponse) {
            /// This should perform after call 1, or call 2 if call 1 failed

            return Parse.Cloud.httpRequest({
                // API call 3
            });
        }
    ).catch(
        function(error) {
            console.log('FAIL');
            return response.error(error);
        }
    );
});

I expected call 3 to be performed even if Call 1 failed, but apparently it does not, it performs the first catch block, but then it performs the last catch block. I thought I caught the error properly when I return a new promise in the catch block?


Solution

  • Long story short, you should have only one catch block for each Promise chain.

    You could refactor your code with async/await blocks like this:

    Parse.Cloud.define("apiCall", async function(request, response) {
    
        let response = null;
        try {
            response = await Parse.Cloud.httpRequest({
                // API call 1
            })
        } catch (error) {
            console.log({"data": "this is an expected JSON"});
    
            response = Parse.Cloud.httpRequest({
                // API call 2
            });
        }
        try {
            // Use response variable here
            let response2 = Parse.Cloud.httpRequest({
                // API call 3
            });
            return response2;
        } catch (error) {
            console.log('FAIL');
            return response.error(error);
        }
    });
    

    If you want to stick with Promise chain, you can also do this:

    Parse.Cloud.define("apiCall", function(request, response) {
    
        return new Promise((resolve, reject) => {
            Parse.Cloud.httpRequest({
                // API call 1
            })
            .then(function (data) {
                resolve(data);
            })
            .catch(function(error) {
                /// Only perform this if the first call fails
    
                // Return valid json here, to mock the Parse.Cloud.httpRequest below
                console.log({"data": "this is an expected JSON"});
    
                Parse.Cloud.httpRequest({
                    // API call 2
                })
                .then(function (data) {
                    resolve(data);
                })
                .catch(function (error) {
                    reject(error);
                })
            })
        }).then(
            function(httpResponse) {
                /// This should perform after call 1, or call 2 if call 1 failed
    
                return Parse.Cloud.httpRequest({
                    // API call 3
                });
            }
        ).catch(
            function(error) {
                console.log('FAIL');
                return response.error(error);
            }
        );
    });