Angular12拦截GraphQL请求响应 如何在响应处理器中接入通知服务
实现方案
注意事项
- 不要硬编码错误提示文本,要把实际捕获的错误内容传给通知服务,方便用户排查问题
- 通知服务的调用必须写在抛出错误之前,
throw语句执行后会终止当前函数上下文后续代码执行,写在后面会无法触发通知 - 如果你的项目对单元测试有要求,建议不要直接在函数内部硬导入全局通知服务,通过参数注入的方式耦合度更低,更易测试
最简实现(全局单例通知服务)
如果你的项目里 notificationsService 是全局可访问的单例服务,直接修改 handleError 函数即可,同时可以优化错误提示的可读性:
const handleError = (errors: Array<string | {message?: string}>) => { if (Array.isArray(errors) && errors.length) { // 提取友好的错误提示,优先取错误对象的message字段,没有就直接序列化 const errorMsg = errors.map(error => { if (typeof error === 'string') return error return error.message || JSON.stringify(error) }).join(';') // 调用通知服务,建议使用错误级别的通知样式 notificationsService.show(errorMsg, { type: 'error' }) const errorArrayToString = errors.map(error => JSON.stringify(error)).toString(); throw new Error(errorArrayToString); } };
如果业务逻辑确认 errors 确实是字符串数组,去掉对象判断逻辑即可。
低耦合依赖注入实现(推荐)
如果希望代码更易测试,不依赖全局服务,可以改造 handleResponse 函数接收通知服务作为参数:
// 给handleResponse增加可选的通知服务参数 export const handleResponse = ( operation: DocumentNode, notificationsService?: { show: (msg: string, options?: any) => void } ): OperatorFunction<any, any> => { return pipe( map((response: any) => { const definition = operation.definitions[0] as OperationDefinitionNode; const selection = definition.selectionSet.selections[0] as FieldNode; const selectionName = selection.name.value ?? null; if (!selectionName) { throw new Error(`${selection.kind} name must be present.`); } if (response.data[selectionName]?.errors) { // 把通知服务传给handleError handleError(response.data[selectionName].errors, notificationsService); } return response.data[selectionName]; }), ); }; // 改造handleError接收通知服务参数 const handleError = ( errors: string[], notificationsService?: { show: (msg: string, options?: any) => void } ) => { if (Array.isArray(errors) && errors.length) { const errorMsg = errors.map(error => JSON.stringify(error)).join(';'); // 传入了通知服务才调用,完全兼容旧逻辑 notificationsService?.show(errorMsg, { type: 'error' }) throw new Error(errorMsg); } };
使用时直接传入项目内的通知服务实例即可:
handleResponse(yourOperation, notificationsService)
内容的提问来源于stack exchange,提问作者Andrey Seluykov
相关产品推荐
相关产品推荐

