Adam Reed
Adam Reed

Reputation: 59

Chaining promises - correct methodology

I'm trying to create an excel add-in using Javascript that requires asynchronous functions return a JS promise to Excel and that the promise is resolved with the final value using the callback function. I am new to promises and have spent hours reading and testing this out with no success, and was hoping someone could help me understand what I'm doing wrong. Below is the code:

function TEST(num1) {
    return new Promise(function (resolve) {  
        var corsproxy = "https://cors-anywhere.herokuapp.com/"
        var apiurl = "https://randomapi.com/testapi"

        var data = getData(corsproxy+apiurl).then(function(result){
            console.log ("here it comes")    
            console.log(result.meta.status)  /// This returns "Success"
            return (result.meta.status)      /// I need this to be resolved
        })
        console.log("last")
        resolve(data)
    })
};

/// Get JSON
    function getData(url) {
        return new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.responseType = 'json';
            xhr.onload = function () {
                try {
                    if (xhr.status === 200) {
                        resolve(xhr.response);
                    }
                    else if (xhr.status !== 200) {
                        reject({
                            error: 'Request failed. ' + xhr.response
                        });
                    }
                } catch (e) {
                    reject({
                        error: e
                    });
                }
            };
            xhr.send();
        });
    }

The second function getData is working as intended and returning a JS Object. What I'm trying to accomplish with the TEST function is:

  1. Create a new promise - this needs to be resolved/returned as "Success"
  2. Call the API data with getData(temporarily running through a proxy to bypass CORS erros)
  3. Extract the meta.status value ("Success")

I've tried a number of different things but the current code write "last" and resolves an undefined data before the getData function completes. Changing the "return (result.meta.status)" to "resolve (result.meta.status)" also doesn't help.

Any assistance with what I'm doing wrong would be greatly appreciated.

Upvotes: 0

Views: 55

Answers (2)

James Gould
James Gould

Reputation: 4702

You can use async/await since ES6 that solves a lot of this headache by simplifying the chain process into using await statements when letting promises resolve. I've updated your code block to use it, take a look:

async function TEST(num1) {
    return new Promise(function (resolve) {  
        var corsproxy = "https://cors-anywhere.herokuapp.com/"
        var apiurl = "https://randomapi.com/testapi"

        var result = await getData(corsproxy+apiurl);

        resolve(result.meta.status)
    })
};

/// Get JSON
function getData(url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.responseType = 'json';
        xhr.onload = function () {
            try {
                if (xhr.status === 200) {
                    resolve(xhr.response);
                }
                else if (xhr.status !== 200) {
                    reject({
                        error: 'Request failed. ' + xhr.response
                    });
                }
            } catch (e) {
                reject({
                    error: e
                });
            }
        };
        xhr.send();
    });
}

Changes made:

  • TESTis now an async function.
  • Rather chaining the resolved promise from getData and resolving in TEST, you simply await the response from getData and then resolve it.

Upvotes: 1

mpm
mpm

Reputation: 20154

function TEST(num1) {
        var corsproxy = "https://cors-anywhere.herokuapp.com/"
        var apiurl = "https://randomapi.com/testapi"

        return getData(corsproxy+apiurl)
}

TEST(valofnum1).then(function(result){
            console.log ("here it comes")    
            console.log(result.meta.status)  /// This returns "Success"
            return (result.meta.status)      /// Needs to be resolved
        })

that's how you chain promises. you don't resolve a promise within another promise,

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

Upvotes: 1

Related Questions