Search code examples
node.jsedamam-api

how to get API data out of a node.js function


I'm pretty new to JS and very very new to Node. I'm trying to make a very simple app that pulls JSON data from the edamam API (https://rapidapi.com/edamam/api/edamam-nutrition-analysis). I've got the API working, and I now want to use the data that the request returns, but it's stuck inside a callback function and I can't figure out how to access it outside of the function that retrieves it.

From what I can tell, it's something to do with the async nature of Node. I've tried re-ordering it in every way I can think of (for over 6 hours!), but all I ever get is undefined variables. I'm figuring that's because they haven't been set yet, but I don't quite have enough of a handle on callback functions to understand how to fix this.

Eventually I want to be able to use the JSON data to update the contents of HTML elements.

   const unirest = require('unirest');


   var getNutritionInfo = {
        mkString: function(foodStr){
          var ingredients = new Array();
          ingredients.push(foodStr);
          console.log(foodStr)
              params = {
              ingr: ingredients,

          };

          esc = encodeURIComponent;
          query = Object.keys(params)
              .map(k => esc(k) + '=' + esc(params[k]))
              .join('&');

          foodQuery = query.replace(/%20/g,"+");
          return(foodQuery);
        },

        analyse: function(foodStr){
          var cals;
          url = "https://edamam-edamam-nutrition-analysis.p.rapidapi.com/api/nutrition-data"
          searchQuery = getNutritionInfo.mkString(foodStr);
          function requestData(callback){
              unirest.get(url+"?" + searchQuery)
              .header("X-RapidAPI-Key", "c5c219c7b0mshbf5b602f68caddep1cd8cfjsn01a1be1f45a4")
              .end(function (result) {
                cals = result.body.totalNutrients.ENERC_KCAL.quantity;
                console.log(cals + " first");
                callback();

            });
          }
          requestData(function(){
            console.log(cals + " second");

                getNutritionInfo.getData();


          });
        },

        getData: function(){
          var calories = getNutritionInfo.analyse.cals;
          console.log(calories + " third");
          return calories;
        }
};

the final console.log is ALWAYS undefined, whereas I am wanting it to return the value on line of cals (result.body.totalNutrients.ENERC_KCAL.quantity);

Also, I'm very sorry. I'm aware that there must be cleaner ways to organise functions and format code. I'll get there eventually :)


Solution

  • the final console.log is ALWAYS undefined, whereas I am wanting it to return the value on line of cals (result.body.totalNutrients.ENERC_KCAL.quantity);

    This is because of the asynchronous nature of the nodejs. To get value from requestData(), you need to pass cal as a value to the callback.

    Making those changes,

    'use strict';
    
    const unirest = require('unirest');
    
    var getNutritionInfo = {
      mkString: function (foodStr) {
        var ingredients = new Array();
        ingredients.push(foodStr);
        console.log(foodStr)
        params = {
          ingr: ingredients,
    
        };
    
        esc = encodeURIComponent;
        query = Object.keys(params)
          .map(k => esc(k) + '=' + esc(params[k]))
          .join('&');
    
        foodQuery = query.replace(/%20/g, "+");
        return (foodQuery);
      },
    
      analyse: function (foodStr) {
        url = "https://edamam-edamam-nutrition-analysis.p.rapidapi.com/api/nutrition-data"
        searchQuery = getNutritionInfo.mkString(foodStr);
        function requestData(callback) {
          unirest.get(url + "?" + searchQuery)
            .header("X-RapidAPI-Key", "c5c219c7b0mshbf5b602f68caddep1cd8cfjsn01a1be1f45a4")
            .end(function (result) {
              let cals = result.body.totalNutrients.ENERC_KCAL.quantity;
              console.log(cals + " first");
              callback(cals); // pass value here
            });
        }
        requestData(function (cals) { // get value after completion
          console.log(cals + " second");
          getNutritionInfo.getData();
        });
      },
    
      getData: function () {
        var calories = getNutritionInfo.analyse.cals;
        console.log(calories + " third");
        return calories;
      }
    };