Home > Blockchain >  How to convert jQuery $getJSON call to vanilla JS using Fetch API
How to convert jQuery $getJSON call to vanilla JS using Fetch API

Time:10-15

I have a site that uses money.js to do realtime currency conversion by getting rates from the Open Currency Exchange API. The JSON data object contains a nested 'rates' object which money.js then uses in a callback function to get data.rates and perform the conversion.

Money.js also provides a wrapper that requires base currency and conversion rates are set in the application and stored in its fx.rates object. These settings are then overwritten by the rates from the API call.

The jQuery implementation works, but I want to convert it to plain js. The Fetch API seems to work until the callback function tries to map fx.rates to data.rates, at this point I get an error: TypeError: Cannot read properties of undefined (reading 'rates’) - this is data.rates not fx.rates. Here is a simplified snippet of the two approaches:

import money from 'money';

// Jquery Version

(function( $ ) {

  // Declare Default Exchange Rates
  var fx = require("money");

  fx.rates = {
    "EUR" : 1.17, 
    "USD" : 1.39,        
    "GBP" : 1,
  }

  // Init Connect To Open Exchange Rates API

  function initOpenExAPI(){ 

    // Load exchange rates data via AJAX:
    $.getJSON(
      // NB: using Open Exchange Rates here, but you can use any source!
      'https://openexchangerates.org/api/latest.json?app_id=XXXXXXXX&base=GBP',
      function(data) {

        // Check money.js has finished loading:
        if ( typeof fx !== "undefined" && fx.rates ) {
          fx.rates = data.rates; 
          fx.base = data.base;
          
        } else {
          // If not, apply to fxSetup global:
          var fxSetup = {
            rates : data.rates,
            base : data.base, 
          }
        }
        initEuroConversion();
      }
    );          

  }

  //Init Money.js conversion

  function initEuroConversion() {
    $('.js-price').each( function( index, element ){
      var value = $(this).data('price');
      fx(value).from('GBP').to('EUR');
    });
  }

  //Init First Call To Open Exchange API On Ready
  $(document).ready(function () {
    initOpenExAPI();
  });

}( jQuery ) );


/**
* Vanilla JS Version
*/

// Declare Default Exchange Rates
const fx = require('money');

fx.rates = {
  "EUR" : 1.15, 
  "USD" : 1.12,        
  "GBP" : 1,
};

fx.base = "GBP";


/**
 * Init Connect To Open Exchange Rates API
 */
function initOpenExAPI(){ 

  // fetch rates
  fetch('https://openexchangerates.org/api/latest.json?app_id=XXXXXXXX&base=GBP')
   .then(response => response.json())
   .then(json => console.log(json))
   .then(function (data) {

    // Check money.js has finished loading:
    // This is where it fails

    if ( typeof fx !== "undefined" && fx.rates ) {
      fx.rates = data.rates; 
      fx.base = data.base;
      
    } else {
      // If not, apply to fxSetup global:
      const fxSetup = {
        rates : data.rates,
        base : data.base, 
      }
    }
    
    // The API call was successful!
    //console.log(data); returns object
    initEuroConversion();

  })
  .catch(function (err) {
    // There was an error
    console.log('Something went wrong.', err);
  });

}

// Money.js conversion

function initEuroConversion() {

  const subTotal = document.querySelectorAll('.js-price');

  subTotal.forEach(el => {
    const value = el.getAttribute('data-price');
    fx(value).from('GBP').to('EUR');    
  });

}

Trying to understand why the callback function using the fetch API doesn't have access to the fx object? Any help would be great

CodePudding user response:

   .then(json => console.log(json))
   .then(function (data) {

    // Check money.js has finished loading:
    // This is where it fails

    if ( typeof fx !== "undefined" && fx.rates ) {
      fx.rates = data.rates;

The callback to the first then in this part of your code:

  1. Receives a JavaScript object (that was parsed from some JSON but isn't JSON itself)
  2. Logs it
  3. Returns the return value of console.log, which is undefined

The second then receives the return value of the previous then, which is undefined, hence your error.

You need each then in the chain to return the value you want the next one to receive.

.then(latest => {
    console.log(latest);
    return latest;
})
  • Related