首页 > 解决方案 > 运行大 JSON 数据时如何防止冻结或挂起

问题描述

运行此代码时如何防止冻结?async/await 可以用作解决方案吗?数据有 18MB 大小,所以它以某种方式冻结。

Validation 有许多案例要通过,数据由 125k 测试用例组成。我怎样才能防止冻结?

 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
        })
      }
    }

标签: javascriptreactjsasync-await

解决方案


您正在谈论的现象是一种称为“阻塞事件循环”的已知事物。

是什么阻止了事件循环?

  1. JS 以单线程、同步方式运行。这意味着每一行都被执行,并且下一行仅在前一行执行后才执行。

  2. 只要您以同步方式工作,如果您使用诸如fetch调用之类的异步函数,Promises并且在 JS 继续运行时,浏览器正在幕后处理更多内容,这是正确的。(幕后发生的事情是任何异步代码都由浏览器处理,然后在完成后发送到事件循环,然后只有在调用堆栈被清除后才将其添加到调用堆栈中)

在获取数据或执行任何异步操作时,JS 将继续运行并且不会阻塞 UI。

  1. 当 JS 代码同步运行时,不能执行任何操作,例如鼠标点击等,有效地导致 UI 卡住。发生这种情况是因为 JS 是同步的,并且在运行 JS 代码时您不能并行执行其他操作。

通常这不会影响用户,因为 JS 代码运行得非常快,但是对于像您这样的情况,您需要运行大型同步代码或在某些情况下需要运行大型动画,这绝对是一个问题。

  1. 所以如果你把所有的代码都变成异步的,在后台运行,JS 会继续执行,UI 不会卡住。

有哪些解决方案?

  1. 将这样的繁重操作移至服务器并异步工作,您的代码将在服务器中运行,不会阻塞事件循环,您的 UI 也不会被冻结。

  2. 使用Web Workers,它使您能够在单独的线程中运行 JavaScript。

  3. 拆分代码并使用requestAnimationFrame - 它允许您在每个帧中运行给定的函数,就在它执行重绘之前。

我绝对推荐第一个选项,前端不适合存储这样的大量数据并执行此类操作,并且应该尽可能轻。

Web Workers 也有限制,虽然它允许您并行运行 JS,但它们有一定的限制,因为您仍然在用户的浏览器上运行它。

至于requestAnimationFrame,运行时间长,管理难度大,绝对不适合你的情况

我还想添加评论中提到的一个很好的资源:

MDN - 强化 JavaScript


推荐阅读