title: Running Heavy JS Tasks w/React Native
body: <p>Looking for answers/feedback/suggestions on how to keep a React Native application UI responsive while executing a computationally heavy JS task.</p>
  
  <p>I must perform a parse of JSON string information, which is application setup data.</p>
  
  <p>I have identified this as a culprit that is causing UI jank in my application. After receiving a JSON string in JS (it is a file loaded natively), I must parse through the JSON to build an "in memory db" for the application. Sudo code looks something like this: </p>
  
  <pre><code>function parseSetup(jsonString) {
    var json = JSON.parse(jsonString); //This can take up to 100+ms for a 3MB JSON file
  
    for (let item of json.items) {
      // Do some parsing
      // Instantiate model objects w/json info
      // could take up to 3000ms
    }
  
    for (let thing of json.things) {
      // Same as above
    }
  
    for (let parent of json.parents) {
      //Same as above
      for (let child of parent) {
        //Same as above, but note this is a nested for loop
      }
    }
  }
  </code></pre>
  
  <p><code>parseSetup</code>, can take up to 5,000+ms (5 seconds). This locks up the JS thread which makes my app appear frozen, as the Native touch events &amp; JS logic are queued up after the parseSetup function. Enter InteractionManager's runAfterInteraction. I have had a bit of success using the runAfterInteraction, but I am basically wrapping every line of code I have with the runAfterInteraction. It feels wrong and it doesn't work quite 100% as some of the functions that become wrapped with runAfterInteraction may take longer than the deadline set by InteractionManagers.setDeadline anyway. So here is what I have ended up with:</p>
  
  <pre><code>function parseSetup(jsonString) {
    var json = JSON.parse(jsonString); //This can take up to 100+ms for a 3MB JSON file
    InteractionManager.setDeadline(30);
  
    for (let item of json.items) {
      InteractionManager.runAfterInteraction(() =&gt; someInnerFunc()); //Could take 50ms
      InteractionManager.runAfterInteraction(() =&gt; someOtherFunc());
    }
  
    for (let thing of json.things) {
      InteractionManager.runAfterInteraction(() =&gt; someInnerFunc());
      InteractionManager.runAfterInteraction(() =&gt; someOtherFunc());
    }
  
    for (let parent of json.parents) {
      InteractionManager.runAfterInteraction(() =&gt; someInnerFunc());
      InteractionManager.runAfterInteraction(() =&gt; someOtherFunc());
      for (let child of parent) {
        InteractionManager.runAfterInteraction(() =&gt; someInnerFunc());
        InteractionManager.runAfterInteraction(() =&gt; someOtherFunc());
      }
    }
  
    //Do the above for more JSON keys (50+ more)
  }
  </code></pre>
  
  <p>Am I understanding correctly that any function that is executed that takes longer than 16.67/ms will block the JS thread? </p>
  
  <p>The penultimate question: is there a better way to go about running a long function like this without locking the JS thread? Thank you</p>