Files
test-repo/docs/.vitepress/theme/components/appendix/concurrency-models/AsyncAwaitDemo.vue
T
sanbuphy 66b2ba6e45 fix: resolve all ESLint errors in Vue components
Fixed 22 ESLint errors across 26 Vue component files:
- Removed TypeScript type annotations from ReadingProgress.vue (converted to JS)
- Removed unused variables, imports, and duplicate function declarations
- Fixed HTML parsing errors (invalid attribute names, unclosed tags)
- Added missing :key directives to v-for loops
- Fixed duplicate object keys (backgroundImage)
- Replaced special characters in comments to avoid parsing issues
- Fixed malformed HTML tags (v-else", 003e attributes)

All warnings were left unchanged as requested. Build now passes with 0 errors.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-20 01:03:38 +08:00

465 lines
9.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="demo-container">
<h4>async/await 机制演示</h4>
<div class="controls">
<el-button
type="primary"
size="small"
:disabled="isRunning"
@click="runExample"
>
{{ isRunning ? '运行中...' : '运行示例' }}
</el-button>
<el-button
size="small"
@click="reset"
>
重置
</el-button>
<el-checkbox
v-model="showDetails"
size="small"
>
显示详细信息
</el-checkbox>
</div>
<div class="code-section">
<div class="code-block">
<div class="code-header">
<span class="code-title">Python asyncio 示例</span>
</div>
<pre class="code-content"><code><span class="keyword">import</span> asyncio
<span class="keyword">async def</span> <span class="function">fetch_data</span>(url):
<span class="comment"># await 挂起让出 CPU</span>
response = <span class="keyword">await</span> aiohttp.get(url)
<span class="comment"># I/O 完成后继续执行</span>
<span class="keyword">return</span> response.json()
<span class="keyword">async def</span> <span class="function">main</span>():
<span class="comment"># 并发执行</span>
tasks = [fetch_data(url) <span class="keyword">for</span> url <span class="keyword">in</span> urls]
results = <span class="keyword">await</span> asyncio.gather(*tasks)</code></pre>
</div>
</div>
<div class="visualization">
<div class="timeline-container">
<h5>执行时间线</h5>
<div class="timeline">
<div class="time-axis">
<div class="axis-label">
0ms
</div>
<div class="axis-label">
50ms
</div>
<div class="axis-label">
100ms
</div>
<div class="axis-label">
150ms
</div>
<div class="axis-label">
200ms
</div>
</div>
<div class="thread-rows">
<div class="thread-row">
<div class="row-label">
事件循环
</div>
<div class="row-track">
<div
class="execution-segment event-loop"
style="width: 100%;"
>
调度中
</div>
</div>
</div>
<div
v-for="task in tasks"
:key="task.id"
class="thread-row"
>
<div class="row-label">
任务 {{ task.id }}
</div>
<div class="row-track">
<template
v-for="(segment, sidx) in task.segments"
:key="sidx"
>
<div
class="execution-segment"
:class="{ 'active': segment.type === 'active', 'io': segment.type === 'io' }"
:style="{ left: segment.start + '%', width: segment.width + '%', backgroundColor: segment.color }"
>
<span
v-if="segment.width > 8"
class="segment-label"
>
{{ segment.type === 'active' ? '执行' : 'I/O' }}
</span>
</div>
</template>
</div>
</div>
</div>
</div>
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-title">
并发任务数
</div>
<div class="stat-value">
{{ tasks.length }}
</div>
</div>
<div class="stat-card">
<div class="stat-title">
总执行时间
</div>
<div class="stat-value">
{{ totalTime }}ms
</div>
</div>
<div class="stat-card">
<div class="stat-title">
I/O 等待时间
</div>
<div class="stat-value">
{{ ioWaitTime }}ms
</div>
</div>
<div class="stat-card">
<div class="stat-title">
CPU 利用率
</div>
<div class="stat-value">
{{ cpuUtilization }}%
</div>
</div>
</div>
</div>
<div class="explanation">
<el-alert
title="async/await 的优势"
type="success"
description="当一个任务遇到 I/O 操作(如网络请求)时,await 会让出 CPU,事件循环调度其他任务执行。I/O 完成后,任务从断点恢复。这种方式让单个线程可以并发处理数千个任务。"
show-icon
:closable="false"
/>
</div>
</div>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
const coroutineCount = ref(1000)
const isRunning = ref(false)
const showDetails = ref(false)
const tasks = ref([])
// 颜色
const colors = ['#409eff', '#67c23a', '#e6a23c', '#f56c6c', '#909399']
// 计算统计数据
const totalTime = computed(() => {
if (tasks.value.length === 0) return 0
// 模拟总时间
return Math.round(50 + tasks.value.length * 10)
})
const ioWaitTime = computed(() => {
return Math.round(totalTime.value * 0.6)
})
const cpuUtilization = computed(() => {
return Math.round(100 - (ioWaitTime.value / totalTime.value) * 100)
})
// 生成任务数据
function generateTasks() {
const count = Math.min(Math.floor(coroutineCount.value / 200), 5)
const newTasks = []
for (let i = 0; i < count; i++) {
const segments = []
let currentPos = 5
// 生成交替的执行和I/O段
for (let j = 0; j < 3; j++) {
// 执行段
const execWidth = 10 + Math.random() * 10
segments.push({
type: 'active',
start: currentPos,
width: execWidth,
color: colors[i % colors.length]
})
currentPos += execWidth
// I/O段
const ioWidth = 15 + Math.random() * 10
segments.push({
type: 'io',
start: currentPos,
width: ioWidth,
color: '#dcdfe6'
})
currentPos += ioWidth
}
newTasks.push({
id: i + 1,
segments,
state: 'ready'
})
}
tasks.value = newTasks
}
// 运行示例
function runExample() {
isRunning.value = true
generateTasks()
// 模拟运行
setTimeout(() => {
isRunning.value = false
}, 2000)
}
// 重置
function reset() {
tasks.value = []
isRunning.value = false
coroutineCount.value = 1000
}
// 监听协程数量变化
watch(coroutineCount, () => {
if (tasks.value.length > 0) {
generateTasks()
}
})
// 初始化
generateTasks()
</script>
<style scoped>
.demo-container {
padding: 20px;
background: #f5f7fa;
border-radius: 6px;
}
h4 {
margin: 0 0 16px 0;
color: #303133;
}
.controls {
display: flex;
gap: 16px;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
}
.slider-label {
font-size: 14px;
color: #606266;
min-width: 100px;
}
.code-section {
margin-bottom: 20px;
}
.code-block {
background: #282c34;
border-radius: 6px;
overflow: hidden;
}
.code-header {
background: #21252b;
padding: 8px 16px;
border-bottom: 1px solid #181a1f;
}
.code-title {
color: #abb2bf;
font-size: 13px;
font-weight: 500;
}
.code-content {
padding: 16px;
margin: 0;
overflow-x: auto;
font-family: 'Fira Code', 'Consolas', monospace;
font-size: 13px;
line-height: 1.6;
}
.keyword {
color: #c678dd;
}
.function {
color: #61afef;
}
.comment {
color: #5c6370;
font-style: italic;
}
.visualization {
margin-bottom: 20px;
}
.timeline-container {
background: white;
border-radius: 6px;
padding: 16px;
margin-bottom: 16px;
}
.timeline-container h5 {
margin: 0 0 12px 0;
color: #303133;
}
.timeline {
position: relative;
}
.time-axis {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #e4e7ed;
margin-bottom: 8px;
}
.axis-label {
font-size: 11px;
color: #909399;
}
.thread-rows {
display: flex;
flex-direction: column;
gap: 8px;
}
.thread-row {
display: grid;
grid-template-columns: 100px 1fr;
gap: 8px;
align-items: center;
}
.row-label {
font-size: 12px;
color: #606266;
text-align: right;
}
.row-track {
position: relative;
height: 24px;
background: #f5f7fa;
border-radius: 4px;
overflow: hidden;
}
.execution-segment {
position: absolute;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
color: white;
font-weight: 500;
}
.execution-segment.io {
background: #dcdfe6 !important;
color: #606266;
}
.execution-segment.event-loop {
background: #409eff;
}
.current-indicator {
position: absolute;
top: 0;
bottom: 0;
width: 2px;
background: #f56c6c;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
}
.stat-card {
background: white;
border-radius: 6px;
padding: 12px;
text-align: center;
}
.stat-title {
font-size: 12px;
color: #909399;
margin-bottom: 4px;
}
.stat-value {
font-size: 20px;
font-weight: bold;
color: #303133;
}
.explanation {
margin-top: 16px;
}
@media (max-width: 768px) {
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.controls {
flex-direction: column;
align-items: stretch;
}
.thread-row {
grid-template-columns: 60px 1fr;
}
}
</style>