Having issues with axios getting and returning data in my custom node

I am trying to use axios to call a URL and return its data. That part is working, but the ordering is not working when used as a function call. I am sure it's something simple, but I am not used to JavaScript.

The code below has two node.warn parts so that I can see what is being returned.
The one in the function node.warn(["Finally", r, e]) shows the correct data, the one after the function call node.warn(["HTTP", httpReq]); is returned first, and shows httpReq as being undefined. It's like the code is not waiting for the function call to execute.

function httpRequest(method, url, headers) {
    var r = null;
    var e = null;

    switch (method) {
        case "GET": {
            axios.get(url)
                .then(response => {
                    r = response.data;
                })
                .catch(error => {
                    e = error;
                })
                .finally(() => {
                    node.warn(["Finally", r, e])
                    return [r, e];
                })
            break;
        }

        case "POST": {
            node.warn("POST");
            break;
        }

        default: {
            raiseError("No method defined", msg);
            break;
        }
    }
}

With the function call of

this.on('input', function(msg, send, done) {
    if ((this.action != "Log Off") && (!flow.sid || flow.sid == undefined)) {
        var url = "http://www.example.com"
        var httpReq = httpRequest("GET", url);
        node.warn(["HTTP", httpReq]);
    }
    done();
})

Just a question first - many people who are new to Node Red bring their "old way" of doing things - wondering have you looked at the HTTP request node to do this for you ? i.e. move your code into the visual paradigm or is there a reason this will not work for you ?

Craig

I have a working subflow performing one specific API call but want to expand the functionality to cover more API calls. The only way to do this without it being a massively huge flow is by creating a custom node

Aaah right - fair enough i guess - i personally would still go with inidividual http nodes unless you are talking 100's of api calls

Craig

you are right .. because axios is async it executes in your httpRequest function and then it moves along to the next thing .. which is the break ? it doesnt return anything at that point

maybe it would be better if you return the axios call (which is a Promise)

function httpRequest(method, url, headers) {

      switch (method) {
        case "GET": {
          return axios.get(url);
        }

        case "POST": {
          node.warn("POST");
        }

        default: {
          raiseError("No method defined", msg);
          break;
        }
      }
    }

... and then use await and a try catch on the input callback (which needs to be async also)

   this.on("input", async function (msg, send, done) {
      var url = "http://www.example.com";

      try {
        var response = await httpRequest("GET", url);
        var httpReq = response.data;
        node.send({ payload: httpReq });
      } catch (err) {
        node.warn(err);
      }
      done();
    });

This is the nature of the async beast.

Add a callback argument to your httpRequest function & call the callback inside the then and catch (get rid of the two variables & the finally)

Thanks, I'll have a play

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.