You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSON.stringify处理大数据阻塞UI,加载动画停滞问题求助

解决JSON.stringify阻塞UI导致加载动画停滞的问题

核心问题是JSON.stringify在主线程处理大数据时阻塞了UI渲染,要让加载动画持续运行,必须把序列化任务移到非主线程执行,以下是两种可行方案:

方案一:Web Worker(最优解)

Web Worker在后台线程独立运行,完全不占用主线程,能保证加载动画流畅转动。

1. 创建Web Worker文件

新建json.worker.ts,专门处理JSON序列化:

self.onmessage = (event) => {
  const rawData = event.data;
  const formattedJson = JSON.stringify(rawData, null, '\t');
  self.postMessage(formattedJson);
};

2. 修改组件逻辑

调整组件中的变量和方法,改用Worker异步获取序列化结果:

import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core';

@Component({
  // 组件元数据
})
export class YourComponent implements OnDestroy {
  data: any; // 原始数据
  jsonView = false;
  loading = false;
  jsonResult?: string; // 存储异步序列化后的结果
  private jsonWorker: Worker;

  constructor(private cdr: ChangeDetectorRef) {
    // 初始化Worker
    this.jsonWorker = new Worker(new URL('./json.worker', import.meta.url));
    // 接收Worker返回的结果
    this.jsonWorker.onmessage = (event) => {
      this.loading = false;
      this.jsonResult = event.data;
      this.cdr.markForCheck();
    };
  }

  handleJsonViewerOpen() {
    this.jsonView = true;
    this.loading = true;
    this.cdr.markForCheck(); // 立即触发UI更新,显示加载动画
    this.jsonWorker.postMessage(this.data); // 给Worker发送待序列化的数据
  }

  ngOnDestroy() {
    this.jsonWorker.terminate(); // 销毁Worker,避免内存泄漏
  }
}

3. 更新模板

根据异步状态显示加载动画或JSON结果:

<button id="btnGetJson" pButton icon="fa fa-file-code-o" pTooltip="Json Viewer" tooltipPosition="bottom" class="p-button-secondary" (click)="handleJsonViewerOpen()"></button> 

<p-dialog [(visible)]="jsonView" header="Json Viewer({{ header }})" positionTop="0" styleClass="custom-dialog" responsive="true" [closable]="false" > 
  <loader [visible]="loading" *ngIf="!jsonResult"></loader>
  <pre *ngIf="jsonResult" class="json-content">{{ jsonResult }}</pre>
</p-dialog>

方案二:拆分序列化任务(应急简易方案)

如果不想引入Web Worker,可以把大任务拆分成小块,用setTimeout让主线程间隙处理UI渲染:

async generateJsonString() {
  this.loading = true;
  this.cdr.markForCheck();

  const jsonParts: string[] = ['{'];
  const dataEntries = Object.entries(this.data);
  
  for (let i = 0; i < dataEntries.length; i++) {
    const [key, value] = dataEntries[i];
    // 序列化单个键值对
    const entryStr = `"${key}": ${JSON.stringify(value)}`;
    jsonParts.push(entryStr);
    if (i < dataEntries.length - 1) jsonParts.push(',');
    
    // 每处理10个条目就让出主线程,更新UI
    if (i % 10 === 0) {
      await new Promise(resolve => setTimeout(resolve, 0));
      this.cdr.markForCheck();
    }
  }
  
  jsonParts.push('}');
  this.jsonResult = jsonParts.join('\n\t');
  this.loading = false;
  this.cdr.markForCheck();
}

// 修改打开弹窗的方法
handleJsonViewerOpen() {
  this.jsonView = true;
  this.generateJsonString();
}

注意:方案二适合数据结构不太复杂的场景,若数据层级极深,还是Web Worker的效果更稳定。

内容的提问来源于stack exchange,提问作者Askyy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:35:15