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 里统一转成可读文案即可。
/** 把 reject / 异常转成可展示的字符串 */
export function formatPrintError(err, fallback = '未知错误') {
if (!err) return fallback;
if (typeof err === 'string') return err;
if (err instanceof Error && err.message) return err.message;
if (typeof err === 'object' && err !== null) {
if (typeof err.message === 'string' && err.message) return err.message;
if (typeof err.msg === 'string' && err.msg) return err.msg;
}
try { return JSON.stringify(err); } catch { return String(err); }
}
业务侧写法(与在线样例一致):
import webPrintPdf from 'web-print-pdf';
import { formatPrintError } from './print-error.js';
async function onPrintClick() {
try {
const status = await webPrintPdf.utils.getConnectStatus();
if (status.success !== true) throw status;
const result = await webPrintPdf.printHtml(
document.getElementById('area').innerHTML,
{ paperFormat: 'A4', printBackground: true },
{ paperFormat: 'A4' },
{ action: 'print', requestTimeout: 15 }
);
console.log('打印成功', result);
} catch (err) {
alert(formatPrintError(err)); // 或 toast / ElMessage
}
}
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 提示:
// 所有回包(成功 + 失败)都会触发
webPrintPdf.utils.onResponse((msg) => {
console.log('[print-ws]', msg.type, msg.success, msg.message || '');
});
// 仅 WebSocket 传输错误(如连接异常)
webPrintPdf.utils.onError((e) => {
console.error('[print-ws-error]', e);
});
| 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,对比环境差异