javascript - 运行大 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
})
}
}
解决方案
您正在谈论的现象是一种称为“阻塞事件循环”的已知事物。
是什么阻止了事件循环?
JS 以单线程、同步方式运行。这意味着每一行都被执行,并且下一行仅在前一行执行后才执行。
只要您以同步方式工作,如果您使用诸如
fetch
调用之类的异步函数,Promises
并且在 JS 继续运行时,浏览器正在幕后处理更多内容,这是正确的。(幕后发生的事情是任何异步代码都由浏览器处理,然后在完成后发送到事件循环,然后只有在调用堆栈被清除后才将其添加到调用堆栈中)
在获取数据或执行任何异步操作时,JS 将继续运行并且不会阻塞 UI。
- 当 JS 代码同步运行时,不能执行任何操作,例如鼠标点击等,有效地导致 UI 卡住。发生这种情况是因为 JS 是同步的,并且在运行 JS 代码时您不能并行执行其他操作。
通常这不会影响用户,因为 JS 代码运行得非常快,但是对于像您这样的情况,您需要运行大型同步代码或在某些情况下需要运行大型动画,这绝对是一个问题。
- 所以如果你把所有的代码都变成异步的,在后台运行,JS 会继续执行,UI 不会卡住。
有哪些解决方案?
将这样的繁重操作移至服务器并异步工作,您的代码将在服务器中运行,不会阻塞事件循环,您的 UI 也不会被冻结。
使用Web Workers,它使您能够在单独的线程中运行 JavaScript。
拆分代码并使用requestAnimationFrame - 它允许您在每个帧中运行给定的函数,就在它执行重绘之前。
我绝对推荐第一个选项,前端不适合存储这样的大量数据并执行此类操作,并且应该尽可能轻。
Web Workers 也有限制,虽然它允许您并行运行 JS,但它们有一定的限制,因为您仍然在用户的浏览器上运行它。
至于requestAnimationFrame
,运行时间长,管理难度大,绝对不适合你的情况
我还想添加评论中提到的一个很好的资源:
推荐阅读
- javascript - 如何将按钮的值传递给 Flask Python 函数
- c++ - 在多线程函数中返回共享的 const 指针会导致计时问题
- python - Python:如何找到列表之间的相似性,然后找到第二个最相似的,然后是第三个,等等
- python-3.x - 在 Docker 镜像中安全地存储哈希
- ibm-watson - 沃森语音到 node.js 中的文本问题
- jenkins - Jenkins Pipeline sleep(10) 阻止功能完成
- python - 在烧瓶中使用闪存时如何仅显示唯一消息
- image-processing - 在深度学习中,一个类的权重损失高于其他类
- cpu-architecture - RISC V手动混淆:指令格式VS立即格式
- javascript - Can't access innerHTML of child element in sortable list