🚀 TaskClient 使用示例

TaskClient 是一个异步任务管理库,用于简化前端与后端LLM API的交互。 它提供了任务创建、状态轮询、结果获取等功能,支持长时间运行的分析任务。

1. 基本用法

创建任务并轮询状态

// 1. 创建TaskClient实例
const client = new TaskClient({
    debug: true  // 启用调试日志
});

// 2. 创建异步任务
const {task_id, estimated_time} = await client.createTask('ActorNetworkAnalysis', {
    text: '智慧城市项目中的多元主体协同治理机制研究'
});

// 3. 轮询任务状态
client.pollStatus(
    task_id,
    // onUpdate: 进度更新回调
    (status) => {
        console.log('进度:', status.progress + '%');
        console.log('消息:', status.message);
        updateProgressBar(status.progress);
    },
    // onComplete: 完成回调
    (result) => {
        console.log('完成!', result.result);
        displayResult(result.result);
    },
    // onError: 错误回调
    (error) => {
        console.error('失败:', error);
        displayError(error);
    }
);

2. 迁移指南:从同步到异步

❌ 修改前(同步方式)

async function analyzeText() {
    const text = document.getElementById('textInput').value;

    showLoading();

    try {
        // ❌ 直接调用LLM API
        // ❌ 前端阻塞30-120秒
        const response = await fetch('backend/api/ActorNetworkAnalysisAPI.php', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({ text })
        });

        const result = await response.json();

        // ❌ 用户只能看到加载中...
        // ❌ 无法知道进度
        // ❌ 可能超时失败

        displayResult(result);
    } catch (error) {
        handleError(error);
    }
}

✅ 修改后(异步方式)

async function analyzeText() {
    const text = document.getElementById('textInput').value;
    const client = new TaskClient();

    try {
        // ✅ 创建任务,立即返回
        const {task_id} = await client.createTask('ActorNetworkAnalysis', {
            text
        });

        console.log('任务已创建:', task_id);

        // ✅ 轮询状态,显示进度
        client.pollStatus(
            task_id,
            (status) => {
                // ✅ 实时进度更新
                document.getElementById('progress').style.width = status.progress + '%';
                document.getElementById('message').textContent = status.message;
            },
            (result) => {
                // ✅ 显示结果
                displayResult(result.result);
            },
            (error) => {
                // ✅ 显示错误
                displayError(error);
            }
        );

    } catch (error) {
        handleError(error);
    }
}

3. 交互式演示

测试TaskClient

4. API 参考

TaskClient 构造函数

new TaskClient(options)

选项参数:
- baseURL: string - API基础URL(默认使用config.js)
- pollInterval: number - 初始轮询间隔(默认3000ms)
- maxPollInterval: number - 最大轮询间隔(默认30000ms)
- debug: boolean - 调试模式(默认false)

方法列表

// 创建异步任务
await createTask(agentName, inputData)
→ Promise<{task_id, estimated_time}>

// 轮询任务状态
pollStatus(taskId, onUpdate, onComplete, onError)
→ {stop: Function} // 返回控制器

// 获取状态(单次)
await getStatus(taskId)
→ Promise<{status, progress, message}>

// 获取结果
await getResult(taskId)
→ Promise<{status, result}>

// 取消任务
await cancelTask(taskId)
→ Promise

// 停止所有轮询
stopAllPolling()

// 销毁客户端
destroy()

5. 最佳实践

✅ 推荐做法

⚠️ 注意事项

6. 完整示例:行动者网络分析

HTML结构

<!-- 输入区域 -->
<textarea id="textInput"></textarea>
<button id="analyzeBtn" onclick="analyzeText()">分析</button>

<!-- 进度显示 -->
<div id="progressSection" style="display:none;">
    <div class="progress-bar">
        <div id="progressFill" style="width:0%"></div>
    </div>
    <div id="statusMessage"></div>
</div>

<!-- 结果显示 -->
<div id="resultSection" style="display:none;">
    <div id="resultContent"></div>
</div>

JavaScript代码

// 1. 引入依赖
<script src="shared/js/config.js"></script>
<script src="shared/js/task-client.js"></script>

// 2. 创建全局客户端实例
const taskClient = new TaskClient({
    debug: false
});

// 3. 分析函数
async function analyzeText() {
    const text = document.getElementById('textInput').value;

    if (!text || text.trim().length < 10) {
        alert('请输入至少10个字符的文本');
        return;
    }

    // 禁用按钮
    document.getElementById('analyzeBtn').disabled = true;

    try {
        // 显示进度
        document.getElementById('progressSection').style.display = 'block';
        document.getElementById('resultSection').style.display = 'none';

        // 创建任务
        const {task_id, estimated_time} = await taskClient.createTask('ActorNetworkAnalysis', {
            text: text
        });

        console.log('任务创建成功:', task_id);
        console.log('预计时间:', estimated_time, '秒');

        // 保存任务ID(用于取消)
        window.currentTaskId = task_id;
        document.getElementById('cancelTaskBtn').disabled = false;

        // 轮询状态
        taskClient.pollStatus(
            task_id,
            // onUpdate
            (status) => {
                const progress = status.progress || 0;
                const message = status.message || '处理中...';

                document.getElementById('progressFill').style.width = progress + '%';
                document.getElementById('progressFill').textContent = progress + '%';
                document.getElementById('statusMessage').textContent = message;
            },
            // onComplete
            (result) => {
                document.getElementById('progressSection').style.display = 'none';
                document.getElementById('resultSection').style.display = 'block';
                document.getElementById('resultContent').textContent =
                    JSON.stringify(result.result, null, 2);
                document.getElementById('analyzeBtn').disabled = false;
                document.getElementById('cancelTaskBtn').disabled = true;
            },
            // onError
            (error) => {
                document.getElementById('progressSection').style.display = 'none';
                alert('分析失败: ' + error.message);
                document.getElementById('analyzeBtn').disabled = false;
                document.getElementById('cancelTaskBtn').disabled = true;
            }
        );

    } catch (error) {
        alert('创建任务失败: ' + error.message);
        document.getElementById('analyzeBtn').disabled = false;
    }
}

// 4. 取消函数
async function cancelTask() {
    if (window.currentTaskId) {
        try {
            await taskClient.cancelTask(window.currentTaskId);
            alert('任务已取消');
            document.getElementById('progressSection').style.display = 'none';
            document.getElementById('analyzeBtn').disabled = false;
        } catch (error) {
            alert('取消失败: ' + error.message);
        }
    }
}

// 5. 页面卸载时清理
window.addEventListener('beforeunload', () => {
    taskClient.stopAllPolling();
});