最佳实践
TIP
让你的应用更稳定、更高效、更安全
资源管理
始终调用 destroy()
DANGER
务必在组件卸载时调用 destroy(),避免资源泄漏!
typescript
// React
import { useEffect } from 'react';
import { createRecognizer } from 'xfyun-sdk';
function MyComponent() {
useEffect(() => {
const recognizer = createRecognizer(options);
return () => {
recognizer.destroy(); // 组件卸载时清理
};
}, []);
}
// Vue
import { onUnmounted } from 'vue';
import { createRecognizer } from 'xfyun-sdk';
const recognizer = createRecognizer(options);
onUnmounted(() => {
recognizer.destroy(); // 组件卸载时清理
});避免重复创建实例
typescript
// ❌ 不推荐:每次渲染都创建新实例
function BadComponent() {
const recognizer = createRecognizer(options); // 每次渲染都创建
return <div>...</div>;
}
// ✅ 推荐:使用 useRef 或 onMounted 创建一次
function GoodComponent() {
const recognizerRef = useRef(null);
useEffect(() => {
recognizerRef.current = createRecognizer(options);
return () => recognizerRef.current.destroy();
}, []);
return <div>...</div>;
}错误处理
统一错误处理
typescript
import { createRecognizer, XfyunError } from 'xfyun-sdk';
const recognizer = createRecognizer({
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_API_KEY',
apiSecret: 'YOUR_API_SECRET',
});
recognizer.on('error', (error: XfyunError) => {
// 根据错误码处理
switch (error.code) {
case 10001:
// API 调用失败
showError('服务暂时不可用,请稍后重试');
break;
case 20001:
// 网络连接失败
showError('网络连接失败,请检查网络');
break;
case 30001:
// 音频设备错误
showError('无法访问麦克风,请检查权限');
break;
default:
showError(`错误: ${error.message}`);
}
// 记录到错误追踪服务
errorTrackingService.report(error);
});启用自动重连
typescript
const recognizer = createRecognizer({
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_API_KEY',
apiSecret: 'YOUR_API_SECRET',
enableReconnect: true,
reconnectAttempts: 3,
reconnectInterval: 3000,
});性能优化
启用 WebSocket 持久连接
typescript
const recognizer = createRecognizer({
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_API_KEY',
apiSecret: 'YOUR_API_SECRET',
enableReconnect: true, // 启用自动重连
});
// 多次识别复用同一个实例
recognizer.start();
// ... 识别完成
recognizer.stop();
// 再次识别(复用连接)
recognizer.start();合理设置 VAD 超时
typescript
const recognizer = createRecognizer({
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_API_KEY',
apiSecret: 'YOUR_API_SECRET',
vadEos: 2000, // 静音超时 2 秒(默认 3000ms)
});使用热词提高识别率
typescript
const recognizer = createRecognizer({
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_API_KEY',
apiSecret: 'YOUR_API_SECRET',
hotWords: ['讯飞', '语音', '识别', '人工智能', '机器学习'],
});用户体验
显示识别状态
typescript
const [status, setStatus] = useState<'idle' | 'connecting' | 'recording' | 'error'>('idle');
const recognizer = createRecognizer(options);
recognizer.on('state-change', (state) => {
setStatus(state);
});
// UI 显示
{status === 'connecting' && <Spinner />}
{status === 'recording' && <RecordingIndicator />}
{status === 'error' && <ErrorMessage />}提供清晰的错误提示
typescript
const ERROR_MESSAGES = {
10001: '服务暂时不可用,请稍后重试',
20001: '网络连接失败,请检查网络',
30001: '无法访问麦克风,请检查权限',
40001: 'WebSocket 连接失败',
50001: '权限被拒绝',
};
recognizer.on('error', (error) => {
const message = ERROR_MESSAGES[error.code] || error.message;
toast.error(message);
});支持中断和恢复
typescript
const recognizer = createRecognizer(options);
// 暂停
function pause() {
recognizer.stop();
}
// 恢复
function resume() {
recognizer.start();
}
// 清除结果
function clear() {
recognizer.clearResult();
}安全实践
使用环境变量
typescript
// ✅ 推荐
const recognizer = createRecognizer({
appId: import.meta.env.VITE_XFYUN_APP_ID,
apiKey: import.meta.env.VITE_XFYUN_API_KEY,
apiSecret: import.meta.env.VITE_XFYUN_API_SECRET,
});
// ❌ 不推荐
const recognizer = createRecognizer({
appId: '12345678', // 硬编码!
apiKey: 'abcdefg',
apiSecret: 'hijklmn',
});限制 API 使用
typescript
// 添加使用限制
const MAX_RECOGNITION_TIME = 60000; // 60 秒
const startTime = Date.now();
recognizer.on('result', (text) => {
if (Date.now() - startTime > MAX_RECOGNITION_TIME) {
recognizer.stop();
toast.warning('识别时间过长,已自动停止');
}
});测试建议
单元测试
typescript
import { describe, it, expect, vi } from 'vitest';
import { createRecognizer } from 'xfyun-sdk';
describe('Recognizer', () => {
it('应该正确初始化', () => {
const recognizer = createRecognizer({
appId: 'test',
apiKey: 'test',
apiSecret: 'test',
});
expect(recognizer.getState()).toBe('idle');
});
it('应该正确处理错误', () => {
const onError = vi.fn();
const recognizer = createRecognizer({
appId: 'test',
apiKey: 'test',
apiSecret: 'test',
});
recognizer.on('error', onError);
// 模拟错误
// ...
expect(onError).toHaveBeenCalled();
});
});集成测试
typescript
describe('完整识别流程', () => {
it('应该完成一次完整的识别', async () => {
const recognizer = createRecognizer(options);
const results: string[] = [];
recognizer.on('result', (text) => {
results.push(text);
});
await recognizer.start();
await sleep(1000);
recognizer.stop();
expect(results.length).toBeGreaterThan(0);
recognizer.destroy();
});
});监控和日志
启用调试日志
typescript
import { setLogLevel } from 'xfyun-sdk';
// 开发环境
setLogLevel('debug');
// 生产环境
setLogLevel('error');记录关键事件
typescript
import { Analytics } from '@/services/analytics';
recognizer.on('start', () => {
Analytics.track('recognition_started');
});
recognizer.on('result', (text) => {
Analytics.track('recognition_result', { length: text.length });
});
recognizer.on('error', (error) => {
Analytics.track('recognition_error', { code: error.code });
});检查清单
开发阶段
- [ ] 使用环境变量管理 API 凭证
- [ ] 启用调试日志
- [ ] 编写单元测试
- [ ] 测试错误处理
生产阶段
- [ ] 禁用调试日志
- [ ] 启用自动重连
- [ ] 实现错误追踪
- [ ] 添加使用监控
- [ ] 确保所有实例都调用
destroy()