import { useEffect, useState } from 'react' import { Link } from 'wouter' interface UploadProgress { id: string name: string progress: number status: 'uploading' | 'completed' | 'error' speed: string timeRemaining: string } interface DataItem { id: number title: string content: string timestamp: string status: 'loading' | 'loaded' | 'error' } export default function AsyncTestPage() { const [uploads, setUploads] = useState([]) const [dataItems, setDataItems] = useState([]) const [isLoadingData, setIsLoadingData] = useState(false) const [realTimeData, setRealTimeData] = useState([]) const [isRealTimeActive, setIsRealTimeActive] = useState(false) const [longRunningTask, setLongRunningTask] = useState<{ isRunning: boolean progress: number currentStep: string logs: string[] }>({ isRunning: false, progress: 0, currentStep: '', logs: [], }) // 模拟实时数据更新 useEffect(() => { let interval: NodeJS.Timeout if (isRealTimeActive) { interval = setInterval(() => { const newData = `数据更新 ${new Date().toLocaleTimeString()}: ${Math.floor(Math.random() * 1000)}` setRealTimeData((prev) => [newData, ...prev.slice(0, 9)]) // 保持最新10条 }, 2000) } return () => { if (interval) clearInterval(interval) } }, [isRealTimeActive]) // 模拟文件上传 const simulateFileUpload = (fileName: string) => { const uploadId = Date.now().toString() const newUpload: UploadProgress = { id: uploadId, name: fileName, progress: 0, status: 'uploading', speed: '0 KB/s', timeRemaining: '计算中...', } setUploads((prev) => [...prev, newUpload]) // 模拟上传进度 const interval = setInterval(() => { setUploads((prev) => prev.map((upload) => { if (upload.id === uploadId) { const newProgress = Math.min(upload.progress + Math.random() * 15, 100) const speed = `${(Math.random() * 500 + 100).toFixed(0)} KB/s` const timeRemaining = newProgress >= 100 ? '完成' : `${Math.ceil((100 - newProgress) / 10)}秒` // 模拟随机失败 if (newProgress > 50 && Math.random() < 0.1) { clearInterval(interval) return { ...upload, status: 'error' as const, speed: '0 KB/s', timeRemaining: '失败', } } if (newProgress >= 100) { clearInterval(interval) return { ...upload, progress: 100, status: 'completed' as const, speed, timeRemaining, } } return { ...upload, progress: newProgress, speed, timeRemaining, } } return upload }) ) }, 500) } // 模拟数据加载 const loadData = async () => { setIsLoadingData(true) setDataItems([]) // 创建骨架屏数据 const skeletonItems: DataItem[] = Array.from({ length: 6 }, (_, i) => ({ id: i, title: '', content: '', timestamp: '', status: 'loading', })) setDataItems(skeletonItems) // 逐个加载数据项 for (let i = 0; i < 6; i++) { await new Promise((resolve) => setTimeout(resolve, 800 + Math.random() * 1000)) setDataItems((prev) => prev.map((item) => { if (item.id === i) { // 模拟随机加载失败 if (Math.random() < 0.15) { return { ...item, status: 'error', title: '加载失败', content: '数据加载失败,请重试', } } return { ...item, status: 'loaded', title: `数据项 ${i + 1}`, content: `这是第 ${i + 1} 个数据项的内容,包含了一些示例文本用于展示加载效果。`, timestamp: new Date().toLocaleString(), } } return item }) ) } setIsLoadingData(false) } // 模拟长时间运行的任务 const startLongRunningTask = async () => { setLongRunningTask({ isRunning: true, progress: 0, currentStep: '初始化任务...', logs: ['任务开始'], }) const steps = [ { name: '初始化任务...', duration: 2000 }, { name: '连接服务器...', duration: 1500 }, { name: '验证权限...', duration: 1000 }, { name: '下载数据...', duration: 3000 }, { name: '处理数据...', duration: 2500 }, { name: '生成报告...', duration: 2000 }, { name: '保存结果...', duration: 1000 }, { name: '清理资源...', duration: 500 }, ] for (let i = 0; i < steps.length; i++) { const step = steps[i] setLongRunningTask((prev) => ({ ...prev, currentStep: step.name, logs: [...prev.logs, `开始: ${step.name}`], })) // 模拟步骤执行时间 const startTime = Date.now() while (Date.now() - startTime < step.duration) { await new Promise((resolve) => setTimeout(resolve, 100)) const elapsed = Date.now() - startTime const stepProgress = Math.min((elapsed / step.duration) * 100, 100) const totalProgress = ((i + stepProgress / 100) / steps.length) * 100 setLongRunningTask((prev) => ({ ...prev, progress: totalProgress, })) } setLongRunningTask((prev) => ({ ...prev, logs: [...prev.logs, `完成: ${step.name}`], })) // 模拟随机失败 if (i === 3 && Math.random() < 0.2) { setLongRunningTask((prev) => ({ ...prev, isRunning: false, currentStep: '任务失败', logs: [...prev.logs, '错误: 数据下载失败,请重试'], })) return } } setLongRunningTask((prev) => ({ ...prev, isRunning: false, progress: 100, currentStep: '任务完成', logs: [...prev.logs, '任务成功完成!'], })) } const clearUploads = () => { setUploads([]) } const retryFailedUpload = (uploadId: string) => { const failedUpload = uploads.find((u) => u.id === uploadId) if (failedUpload) { setUploads((prev) => prev.filter((u) => u.id !== uploadId)) simulateFileUpload(failedUpload.name) } } const retryDataLoad = (itemId: number) => { setDataItems((prev) => prev.map((item) => { if (item.id === itemId) { return { ...item, status: 'loading', title: '', content: '', timestamp: '' } } return item }) ) setTimeout(() => { setDataItems((prev) => prev.map((item) => { if (item.id === itemId) { return { ...item, status: 'loaded', title: `数据项 ${itemId + 1}`, content: `这是重新加载的第 ${itemId + 1} 个数据项的内容。`, timestamp: new Date().toLocaleString(), } } return item }) ) }, 1000) } return (

异步操作测试

测试等待、加载状态识别和异步操作处理能力

{/* 文件上传进度 */}

文件上传进度

{uploads.length === 0 ? (
点击"开始上传"来模拟文件上传
) : ( uploads.map((upload) => (
{upload.name} {upload.status === 'completed' ? '✓ 完成' : upload.status === 'error' ? '✗ 失败' : '上传中...'}
{upload.progress.toFixed(1)}% {upload.speed} {upload.timeRemaining}
{upload.status === 'error' && ( )}
)) )}
{/* 实时数据更新 */}

实时数据更新

{realTimeData.length === 0 ? (
点击"开始更新"来查看实时数据
) : ( realTimeData.map((data) => (
{data}
)) )}
{/* 数据加载和长时间任务 */}
{/* 数据加载骨架屏 */}

数据加载测试

{dataItems.map((item) => (
{item.status === 'loading' ? (
) : item.status === 'error' ? (

{item.title}

{item.content}

) : (

{item.title}

{item.content}

{item.timestamp}
)}
))}
{/* 长时间运行任务 */}

长时间任务

{longRunningTask.progress > 0 && (
{longRunningTask.currentStep} {longRunningTask.progress.toFixed(1)}%
)} {longRunningTask.logs.length > 0 && (

执行日志:

{longRunningTask.logs.map((log, logIdx) => { const logKey = `${logIdx + 1}-${log.substring(0, 30)}` return (
{log}
) })}
)}
{/* 返回链接 */}
← 返回测试页面列表
) }