Worker 池
了解如何使用 MarkdownWorkerPoll 组件来提升多个 markdown 文档或频繁更新的性能。
为什么使用 Worker 池?
Worker 池提供了几个好处:
- 非阻塞解析:Markdown 解析在 Web Workers 中运行,保持主线程响应
- 并行处理:多个 worker 可以同时解析不同的文档
- 更好的性能:适用于频繁更新 markdown 或多文档的应用
基础 Worker 池用法
使用 MarkdownWorkerPoll 包装多个 MarkdownRenderer 组件:
vue
<script setup lang="ts">
import { ref } from 'vue';
import { MarkdownRenderer, MarkdownWorkerPoll } from '@markdown-next/vue';
import type { ParserOptions } from '@markdown-next/parser';
const doc1 = ref('# 文档 1\n\n第一个文档内容');
const doc2 = ref('# 文档 2\n\n第二个文档内容');
const doc3 = ref('# 文档 3\n\n第三个文档内容');
const parserOptions: ParserOptions = {
extendedGrammar: ['gfm', 'mathjax'],
supportsLaTeX: true,
};
</script>
<template>
<MarkdownWorkerPoll :worker-count="2" :parserOptions="parserOptions">
<div class="documents">
<div class="document">
<h2>文档 1</h2>
<MarkdownRenderer :markdown="doc1" :dynamic="true" />
</div>
<div class="document">
<h2>文档 2</h2>
<MarkdownRenderer :markdown="doc2" :dynamic="true" />
</div>
<div class="document">
<h2>文档 3</h2>
<MarkdownRenderer :markdown="doc3" :dynamic="true" />
</div>
</div>
</MarkdownWorkerPoll>
</template>
<style scoped>
.documents {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
}
.document {
padding: 1rem;
border: 1px solid #e0e0e0;
border-radius: 8px;
background: white;
}
</style>使用 Worker 池的实时编辑器
创建不会阻塞 UI 的 markdown 编辑器:
vue
<script setup lang="ts">
import { ref } from 'vue';
import { MarkdownRenderer, MarkdownWorkerPoll } from '@markdown-next/vue';
const markdown = ref(`
# 实时编辑器示例
这个编辑器使用 worker 池,因此解析在后台进行,不会阻塞 UI。
尝试输入一些复杂的内容:
\`\`\`javascript
// 输入大量代码
for (let i = 0; i < 1000; i++) {
console.log(i);
}
\`\`\`
$$
\\sum_{i=1}^{100} i^2 = \\frac{100 \\cdot 101 \\cdot 201}{6}
$$
`);
const parserOptions = {
supportsLaTeX: true,
extendedGrammar: ['gfm', 'mathjax'],
};
</script>
<template>
<div class="editor-layout">
<MarkdownWorkerPoll :worker-count="1" :parserOptions="parserOptions">
<div class="editor-panel">
<h3>编辑器(在此输入)</h3>
<textarea v-model="markdown" class="editor" placeholder="开始输入 markdown..." />
</div>
<div class="preview-panel">
<h3>实时预览(非阻塞)</h3>
<MarkdownRenderer :markdown="markdown" :dynamic="true" :debounceMs="200" class="preview" />
</div>
</MarkdownWorkerPoll>
</div>
</template>
<style scoped>
.editor-layout {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
height: 700px;
padding: 1rem;
}
.editor-panel,
.preview-panel {
display: flex;
flex-direction: column;
border: 1px solid #ddd;
border-radius: 12px;
padding: 1.5rem;
background: white;
overflow: hidden;
}
.editor {
flex: 1;
width: 100%;
padding: 1rem;
border: 1px solid #e0e0e0;
border-radius: 8px;
font-family: 'Monaco', 'Courier New', monospace;
font-size: 14px;
line-height: 1.6;
resize: none;
}
.preview {
flex: 1;
overflow-y: auto;
padding: 1rem;
background: #fafafa;
border-radius: 8px;
}
</style>最佳实践
Worker 数量
根据你的用例选择合适的 worker 数量:
ts
// 单文档,频繁更新
const workerCount = 1;
// 多文档,适度更新
const workerCount = 2;
// 多文档或重量级解析
const workerCount = navigator.hardwareConcurrency || 4;内存管理
在组件卸载时始终清理 worker 池:
ts
import { onUnmounted } from 'vue';
import { MarkdownWorkerPool } from '@markdown-next/parser';
const pool = new MarkdownWorkerPool({ workerCount: 2 });
onUnmounted(() => {
pool.terminate(); // 重要!
});更多示例请参考英文版本。
