Problem w/JS on a personal app

Hello All.

I’m currently working on a personal project of mine, a calculator of sorts. My problem is that for whatever reason, the calculator never returns the final enthalpy value (can be seen at the end of the code). My JS is pasted below:

$(document).ready(function() {
  console.log('Bonnets');
$('#field').focus();


$('#field').keypress(function(e) {
  var key = (event.keyCode ? event.keyCode : event.which);
  var numbersReactants = [];
  var numbersProducts = [];
  if (key == "13") {
    //Upon enter sign, do an equals check
    var input = $('#field').val();
    if(input.indexOf('=') >= 0) {
      console.log(input);
      var reactants = input.split('=')[0];
      var products = input.split('=')[1];

    //Starts reactants check
    if (reactants.indexOf("+") > 0) {
      reactants = reactants.split("+");
    } else {
      reactants = [reactants];
    }
      for(var i = 0; i<reactants.length; i++) {
        reactants[i] = reactants[i].replace(/\s/g,'');
        if (isNaN(reactants[i][0])) {
          reactants[i] = "1" + reactants[i];
        }
      }
      // Gets numbers

        for (var i = 0; i<reactants.length; i++) {
          $.getJSON("https://enthalpy-api.herokuapp.com/" + reactants[i] + '/', function(result) {
            numbersReactants.push(result);
          });
        }



    //Starts products check
    if (products.indexOf("+") > 0) {
      products = products.split("+");
    } else {
      products = [products];
    }
      for(var i = 0; i<products.length; i++) {
        products[i] = products[i].replace(/\s/g,'');
        if (isNaN(products[i][0])) {
          products[i] = "1" + products[i];
        }
      }

      //Gets products numbers

      for (var i = 0; i<products.length; i++) {
        $.getJSON("https://enthalpy-api.herokuapp.com/" + products[i] + '/', function(result) {
          numbersProducts.push(result);
        });
      }




      //Final Sum


      var productSum = 0;
      for (var i = 0; i<numbersProducts.length; i++) {
        productSum += Number(numbersProducts[i][1]);
      }

      var reactantSum = 0;
      for (var i = 0; i<numbersReactants.length; i++) {
        reactantSum += Number(numbersProducts[i][1]);term
      }


      console.log(numbersReactants);
      console.log(numbersProducts);
      console.log("Final Enthalpy: ", (productSum - reactantSum));
      }
    }
});
});

Haiiiyo!

I played around with your code briefly and here are some things that I found or think are the problems:

  • There is random term in line 74 of the code you posted (reactantSum += Number(numbersProducts[i][1]);term)
  • Otherwise the only issue is that the API calls are asynchronous—if you log numbersReactants and numbersProducts inside the respective getJSON callback functions, you will see that the enthalpies are being returned correctly, but they are only logged after all calculations have been performed with empty arrays and 0’s (I did a quick test with O2(g), H2(g) and H2O(l), which returned 0 kJ/mol, 0 kJ/mol and -285.6 kJ/mol respectively)

Have a read through the jqXHR object section of the jQuery Documentation for jQuery.getJSON.

I hope that helps. :slight_smile:

@honmanyau

I understand what you are saying and maybe I can clear some things up.
The reason why there is a term on line 74 for the reactantSum is because this projects works with an API that I made, and so the index marks I have placed there is to select the enthalpy found in the API. You can click the link to view the documentation, but the basic gist of it is that the API call returns with a format that looks like this: (I have used the sample if I were to make the call:
https://enthalpy-api.herokuapp.com/Ca(OH)2(s)

{
"compound": "Ca(OH)2(s)",
"enthalpy": -986.1
}

Hopefully you can work with me to figure out where my project is going astray.

Haiiiyo.

I think you might want to read through my first response where the problem was already identified—the major one being that the asynchronous API calls are too slow so that by the time the data was retrieved, all other calculations have already been done. The link I provided also demonstrates how to use the jqXHR object that is returned from a the jQuery.getJSON() method; you may also find the MDN Documentation on Promise useful.

I read the documentation just now and serendipitously realised that Promise.all() could solve your for-loop problem along with map(). I haven’t personally used it in any projects before but I gave it a go on CodePen out of curiosity and it seems to work, the code is a lot prettier than using a counter inside a for loop:

let reactantEnthalpicData = [];

let getReactants = function() {
    return Promise.all(reactants.map(reactant, index) => {
        return jQuery.geJSON(url + reactants[i], (data) => {
            reactantEnthalpicData.push(data);
        });
    });
}

You can have that chain it with with .then(getReactants) after a Promise that processes user input, followed by the same for products, and finally calculate the heat of reaction.

If I’m not mistaken the random term after the semicolon in line 74 is an error and has nothing to do with your API, and it produces an error—I wasn’t referring to reactantSum as a term of the equation.

I hope that helps, that’s all from me. :slight_smile:

EDIT: typos!

@honmanyau

This actually really helped a lot. I’m starting to understand what Promises mean. I pasted this into my code and corrected for my own variable names and it says there is a syntax error. I don’t see one, so do you have any idea on how I can implement this into my code? I’m sorry if this seems elementary.