How to prevent freeze or hang when running big JSON data

Viewed 731

How can I prevent the freeze when running this code? Does async/await can be use as a solution? The data has 18MB size so it freeze somehow.

The Validation have many cases to pass through and the data consist of 125k test case. How can I possibly prevent the freeze?

 const getEachValueByLine = useCallback(
    () => {
      if (IsJsonString(multipleValue)) {
        setInvalidFormat(true)
        isValidRegex ? setValidRegex(true) : setValidRegex(false)
        const parseValue = Object.entries(JSON.parse(multipleValue))
        const addId = parseValue.map((item, index) => ({ id: index, case: item[0], expected: item[1] }))
        handleMultiValidate(addId)
      } else {
        setInvalidFormat(false)
      }
    },
    [handleMultiValidate, multipleValue],
  )

  const handleMultiValidate = (data) => {
      const validateArr = []
      if (data.length > 0) {
        data.forEach((value) => {
          if (validRegex && customRegex !== '') {
            validateArr.push({
              type: multiValidateBy,
              data: value.case,
              acceptType: [
              ],
              isDecimal: isDecimal,
              isCustomRegex: isCustomRegex,
              localisedRegexCode: localisedRegexCode,
              customRegex: validRegex ? customRegex : ''
            })
          } else {
            validateArr.push({
              type: multiValidateBy,
              data: value.case,
              acceptType: [
              ],
              isDecimal: isDecimal,
              isCustomRegex: isCustomRegex,
              localisedRegexCode: localisedRegexCode
            })
          }
        })
        const result = validator(validateArr)
        result['data'].map((res, i) => {
          if (res.data === data[i].case) {
            res.expected = data[i].expected
          }
          return res
        })
        setMultiResult(result)
      } else {
        setMultiResult({
          status: true
        })
      }
    }
1 Answers

The phenomena you are talking about is a known thing called 'blocking the event loop'.

What is blocking the event loop?

  1. JS run in a single thread, synchronous way. This means that each line gets executed and and following line gets executed only after the previous line did.

  2. This is true as long as you're working in a synchronous way, if you use asynchronous functions such as fetch calls, Promises and more are being handled by the browser behind the scenes while JS continues to run. (What happens behind the scenes is any async code is handled by the browser, then sent to the event loop upon finishing which then adds it to the call stack only after the call stack is clear)

While fetching the data or performing any asynchronous action JS will continue to run and not block the UI.

  1. While JS code is running synchronously, you can't perform any actions such as mouse clicks, etc, effectively causing the UI to become stuck. This is happening because JS is synchronous, and while running JS code you can't do other things in parallel.

Usually this doesn't affect the user as JS code runs very fast however this is definitely a problem with situations like yours where you have big synchronous code that needs to run or in some cases big animations that needs to run.

  1. So if you were to move all that code to be asynchronous, going through it will happen in the background, JS will continue to execute and the UI won't be stuck.

What are the solutions?

  1. Move heavy operations like this to a server and work asynchronously, your code will run in the server and not block the event loop and your UI won't be froze.

  2. Use Web Workers, which enable you to run JavaScript in a separate thread.

  3. Splitting your code and using requestAnimationFrame - which allow you to run a given function in each frame, just before it performs a repaint.

I definitely recommend the first option, the Front End is not meant for storing heavy data like this and performing such operations, and should be as light as possible.

Web Workers have limitations as well and while it allows you to run JS in parallel they have certain limitations because you are still running this on the user's browser.

As for requestAnimationFrame, it takes longer to run and hard to manage, definitely not a fit for your case

I'd also like to add a great resource mentioned in the comments:

MDN - Intensive JavaScript

Related