Loading, parsing, and displaying a JSON file I recently have been working on loading a local JSON file parsing it and displaying it using Javascript and I think I got it to where I really like it. I would like to know if anyone knows if there is a "purer" way of doing this using just Javascript without libraries.



&lt;!DOCTYPE html&gt;
&lt;meta charset="UTF-8" /&gt;
&lt;input type="file" id="files" name="files" accept=".json"/&gt;
&lt;output id="list"&gt;&lt;/output&gt;
&lt;div id="traveler_num"&gt;&lt;/div&gt;
&lt;div id="first_name"&gt;&lt;/div&gt;

&lt;script&gt;

  //stores the output of a parsed JSON file
  const parsed = jsonText =&gt; JSON.parse(jsonText);
  //creates a new file reader object
  const fr = new FileReader();

  function writeInfo (data) {
    //modifies the DOM by writing info into different elements
    document.getElementById('traveler_num').innerHTML = 'Traveler: ' + data.traveler_num;
    document.getElementById('first_name').innerHTML = 'First Name: ' + data.first_name;
  };

  function handleFileSelect (evt) {
    //function is called when input file is Selected
    //calls FileReader object with file
    fr.readAsText(evt.target.files[0])
  };

  fr.onload = e =&gt; {
    //fuction runs when file is fully loaded
    //parses file then makes a call to writeInfo to display info on page
    writeInfo(parsed(e.target.result));
  };

  //event listener for file input
  document.getElementById('files').addEventListener('change', handleFileSelect, false);

&lt;/script&gt;
handleFileSelect is an Impure Function
handleFileSelect has in your code snippet a dependence to fr which is decleraded outside of the function. To make the function pure you can pass fr as argument.
// impure..
function handleFileSelect (evt) {
    fr.readAsText(evt.target.files[0])
}

// pure
function handleFileSelect (fr, evt) {
    fr.readAsText(evt.target.files[0])
}

Put Side Effects Into a Wrapper

A pure function returns for the same input always the same output.

The function writeInfo contains side effects because we access the DOM. We could wrap the DOM functions in to a wrapper called IO which will always return a function - always the same function.


const IO = x =&gt; ({
    map: (fn) =&gt; IO(x(fn)),
    run: () =&gt; x()
})

// more about compose and the benefits on
// https://medium.com/javascript-scene/composing-software-an-introduction-27b72500d6ea
const compose = (f, g) =&gt; x =&gt; f(g(x))

const getElementById = id =&gt; IO(() =&gt; document.getElementById(id))
const writeInnerHTML = value =&gt; element =&gt; IO(() =&gt; element.run().innerHTML = value)

const selectAndWrite = value =&gt; compose(
  writeInnerHTML(value),
  getElementById
)

const writeInfo = data =&gt; IO(() =&gt; {
  selectAndWrite('Traveler: ' + data.traveler_num)('traveler_num').run()
  selectAndWrite('First Name: ' + data.first_name)('first_name').run()
})

// ONLY this call is impure
writeInfo({
  traveler_num: 500,
  first_name: 'Steven'
}).run()
&lt;ul&gt;
  &lt;li id="traveler_num"&gt;&lt;/li&gt;
  &lt;li id="first_name"&gt;&lt;/li&gt;
&lt;ul&gt;



Either You Can Parse to a JSON or Not..
In the following I want to introduce a functor calles Either which is split into to functors Left and Right. If we can parse a string succesfully we will return a Right with the parsed value otherwise we will return Left with an error message.


const Left = x =&gt; ({
  map: (fn) =&gt; Left(x),
  get: () =&gt; x
})

const Right = x =&gt; ({
  map: (fn) =&gt; Right(fn(x)),
  get: () =&gt; x
})

const tryFunction = (errorMessage, fn) =&gt; x =&gt; {
  try {
    return Right(fn(x))
  } catch (error) {
    return Left(errorMessage)
  }
}

const parseToJson = tryFunction('Can\'t pase to JSON', JSON.parse)

console.log('should be {"name": "Random Name"}:', parseToJson('{"name": "Random Name"}').get())
console.log('should be "Can\'t pase to JSON":', parseToJson('{name: Random Name}').get())



References
The free online book mostly-adequate-guide is very good
The series composing-software is a good way to start