web-print-pdf 前端错误处理标准 - 连接与统一报错
三层错误:分清来源即可,不必拆多个 catch
| 层级 | 何时触发 | 识别要点 |
|---|---|---|
| 传输层 | 客户端未启动、端口不通、WS 断开 | try/catch + onError;打印前 getConnectStatus() |
| 业务层 | 客户端已连接,但打印/渲染失败 | 响应 success: false → Promise reject,读 message |
| 应用层 | 参数不合法、未 await、打印机名写死 | 封装校验 + 友好提示;见下文排障表 |
标准响应与失败形态
每条 WebSocket 回包均带 id、type、timestamp、success。npm 包按 id 匹配请求:success: true 时 resolve,false 时 reject 整条 message 对象(不是 Error 实例)。
失败示例:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": 1710000001000,
"type": "printHtml",
"success": false,
"message": "printing exited with exit code: 1",
"data": null
}
成功示例:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": 1710000001000,
"type": "printHtml",
"success": true,
"data": { "pdfPath": "...", "pdfUrl": "...", "pdfFileName": "..." },
"extraOptions": { "action": "print" }
}
统一报错(复制即用)
SDK 失败时 reject 的可能是整条 message 对象(非 Error),直接 alert(err) 往往无效。复制下面这一个函数到项目(如 src/utils/print-error.js),在 catch 里统一转成可读文案即可。
/** formatPrintError */
业务侧写法(与在线样例一致):
import webPrintPdf…
printHtmlByUrl、batchPrint、getPrinterList 等 API 同样包在 try/catch 里,失败时都用 formatPrintError(err) 提示用户。预检不需要另写一套——示例里打印前的 getConnectStatus 未通过时 throw status,与打印失败进同一个 catch 即可。
getConnectStatus 以 success === true 判断就绪(实测 data 常为布尔 true,不是 { connected: true })。连接失败、预检失败、打印失败 reject 的对象都走 formatPrintError。onResponse 与 onError 回调
除 Promise 外,可注册全局回调做日志、埋点或 UI 提示:
// onResponse…
| API | 作用范围 | 适用场景 |
|---|---|---|
try/catch | 单次调用 | 按钮点击、表单提交——给用户即时反馈 |
onResponse | 全局每条回包 | 审计日志、联调、统计成功率 |
onError | WS 传输层 | 监控断线、提示「请重启客户端」 |
业务失败(success:false)走 Promise reject 和 onResponse,不一定触发 onError。勿只用 onError 判断打印是否成功。
常见错误场景与处理
| 现象 / message | 可能原因 | 处理建议 |
|---|---|---|
| WebSocket connection failed / 连接被拒绝 | 客户端未运行或端口被占用 | 启动客户端;核对界面端口;避免多实例抢端口 |
websocket has not been connected |
未 await、在连接完成前连续发请求 | API 必须 await;避免同步链式无等待调用 |
| printing exited with exit code: 1 等出纸失败 | action 为 print 时 printerName 无效;preview 可能回退默认打印机而不报错 | 先 getPrinterList() 选 name;联调打印机用 action: 'print' 测,别只用 preview 判断 |
| preview 成功但打到了错误打印机 | 非法 printerName 在 preview 下可能被忽略 | 正式出纸前用 print 验证打印机;或省略 printerName 明确使用默认机 |
| URL 加载超时 / timeout | 内网页面慢、requestTimeout 过短 | 增大 extraOptions.requestTimeout;检查 cookies/headers |
| 参数校验失败 / 水印无效 | pdfOptions 字段不合法 | 见打印参数详解:watermark.color 用 rgb、angle≥0 等 |
| batchPrint 部分任务失败 | 单条任务参数或内容异常 | 查看客户端「日志」页;拆分批次定位问题任务 |
Vue 3 封装示例
import { ref } from 'vue';
import webPrintPdf from 'web-print-pdf';
import { formatPrintError } from './print-error.js';
export function usePrintWithError() {
const loading = ref(false);
const lastError = ref('');
async function printHtml(html, pdfOptions, printOptions, extraOptions) {
loading.value = true;
lastError.value = '';
try {
const status = await webPrintPdf.utils.getConnectStatus();
if (status.success !== true) throw status;
return await webPrintPdf.printHtml(html, pdfOptions, printOptions, extraOptions);
} catch (err) {
lastError.value = formatPrintError(err);
return null;
} finally {
loading.value = false;
}
}
return { loading, lastError, printHtml };
}
模板里用 lastError 绑定提示组件,loading 禁用按钮即可。
生产环境排障清单
- 浏览器控制台是否有 WS 连到
ws://127.0.0.1:端口/websocket/standard - 客户端「日志」页是否有对应 id 的失败记录
- 用
action: 'preview'先验证 PDF 生成,再排查 printOptions - 换一台机器复现,排除打印机驱动问题
- 到在线样例跑「连接状态」与失败 demo,对比环境差异