Angular+Ionic6中API请求成败时如何调用Toast提示?
问题描述
在Angular + Ionic 6应用中,我需要实现Toast提示,希望在清空购物车、提交订单等事件时展示API返回的消息。我已经尝试了Ionic文档中的实现,但不确定如何正确调用Toast并传递消息。
API响应格式(POSTMAN返回):
{ "message": "You have successfully cleared the cart" }
清空购物车的API调用代码(cart.service.ts):
clearCart() { return from(Preferences.get({key: 'TOKEN_KEY'})).pipe( switchMap(token => { const headers = new HttpHeaders().set('Authorization', `Bearer ${token.value}`); return this.httpClient.delete<ShoppingCart>(`${environment.apiUrl}cart`, {headers, observe: 'response'}); }), catchError(err => { console.log(err.status); if (err.status === 400) { console.log(err.error.message); } if (err.status === 401) { this.authService.logout(); this.router.navigateByUrl('/login', {replaceUrl: true}); } return EMPTY; }), ); }
购物车页面中含Toast实现的清空购物车函数(cart.page.ts):
clearCart() { this.cartService.clearCart().subscribe( (data: any) => { this.products = []; this.totalProducts = 0; this.totalCartPrice = 0; this.successToast(data.body.message, 'bottom'); }, error => { console.log('Error', error); this.errorToast(error, 'bottom'); }); } async successToast(message, position: 'bottom') { const toast = await this.toastController.create({ message: message, duration: 1500, color: 'success', icon: 'checkmark-circle-outline', position }); await toast.present(); } async errorToast(message, position: 'bottom') { const toast = await this.toastController.create({ message: message, duration: 1500, color: 'danger', icon: 'close-circle-outline', position }); await toast.present(); }
请问:
- 当前Toast实现路径是否正确?
- 该如何调用Toast、传递消息?
- 是否需要新建Toast组件?
解答
1. 当前实现路径是否正确?
整体路径是正确的,你已经遵循了Ionic官方的Toast使用规范:通过ToastController创建并展示Toast,且在API请求的回调中触发提示。但存在两个细节问题需要修正:
- 错误回调中直接传递
error对象给errorToast,会导致Toast显示[object Object],需要提取API返回的可读错误消息 - 当前Toast实现和页面耦合度高,多页面复用会产生重复代码,可优化为全局服务
2. 如何正确调用Toast并传递消息?
修正错误消息传递
在cart.page.ts的错误回调中,需要提取API返回的具体错误文本:
error => { console.log('Error', error); // 优先取API返回的错误消息,无则用默认提示 const errorMsg = error.error?.message || '操作失败,请稍后重试'; this.errorToast(errorMsg, 'bottom'); }
调用逻辑说明
- 成功场景:API请求成功后,从响应体
data.body.message获取消息,传入successToast即可,你当前的写法是正确的 - 失败场景:从错误对象中提取
error.error.message(对应API返回的错误信息),确保Toast展示用户能看懂的文本
3. 是否需要新建Toast组件?
不需要单独新建Toast组件,更推荐封装成全局Toast服务,这样所有页面都能复用,避免重复代码。
封装全局Toast服务示例
- 创建
toast.service.ts:
import { Injectable } from '@angular/core'; import { ToastController, ToastOptions } from '@ionic/angular'; @Injectable({ providedIn: 'root' }) export class ToastService { constructor(private toastController: ToastController) { } async showToast(options: ToastOptions) { const toast = await this.toastController.create(options); await toast.present(); } async showSuccess(message: string, position: 'top' | 'middle' | 'bottom' = 'bottom') { await this.showToast({ message, duration: 1500, color: 'success', icon: 'checkmark-circle-outline', position }); } async showError(message: string, position: 'top' | 'middle' | 'bottom' = 'bottom') { await this.showToast({ message, duration: 1500, color: 'danger', icon: 'close-circle-outline', position }); } }
- 在页面中使用该服务:
修改cart.page.ts,注入ToastService替代页面内的Toast方法:
// 导入服务 import { ToastService } from '../services/toast.service'; // 构造函数注入服务 constructor(private cartService: CartService, private toastService: ToastService) {} clearCart() { this.cartService.clearCart().subscribe( (data: any) => { this.products = []; this.totalProducts = 0; this.totalCartPrice = 0; this.toastService.showSuccess(data.body.message); }, error => { console.log('Error', error); const errorMsg = error.error?.message || '清空购物车失败'; this.toastService.showError(errorMsg); }); }
额外优化:将错误提示移到Service层
可以把错误提示逻辑整合到cart.service.ts的catchError中,简化页面的订阅代码:
// 在cart.service.ts中注入ToastService import { ToastService } from './toast.service'; constructor( private httpClient: HttpClient, private authService: AuthService, private router: Router, private toastService: ToastService ) {} clearCart() { return from(Preferences.get({key: 'TOKEN_KEY'})).pipe( switchMap(token => { const headers = new HttpHeaders().set('Authorization', `Bearer ${token.value}`); return this.httpClient.delete<ShoppingCart>(`${environment.apiUrl}cart`, {headers, observe: 'response'}); }), catchError(err => { console.log(err.status); if (err.status === 400) { this.toastService.showError(err.error.message); } if (err.status === 401) { this.authService.logout(); this.router.navigateByUrl('/login', {replaceUrl: true}); } return EMPTY; }), ); }
此时页面的订阅代码可简化为:
clearCart() { this.cartService.clearCart().subscribe( (data: any) => { this.products = []; this.totalProducts = 0; this.totalCartPrice = 0; this.toastService.showSuccess(data.body.message); } ); }
内容的提问来源于stack exchange,提问作者weinde
相关产品推荐
相关产品推荐

