我在服务中有一个可写信号:
private errorEntries: WritableSignal<ErrorEntry[]> = signal<ErrorEntry[]>([])
我有一个吸气剂在服务中:
getErrorEntries(): WritableSignal<ErrorEntry[]> {
return this.errorEntries;
}
和阳极法:
public addError(error: any): void {
const timestamp = new Date().toISOString();
const message = error.message || error.toString();
const stack = error.stack || 'No stack trace available';
const route = this.router.url;
const errorEntry: ErrorEntry = { timestamp, message, stack, route };
this.errorEntries.update((entries) => [...entries, errorEntry]);
}
我在另一个组件中有效果。
showExclamationMark = false;
constructor(private globalErrorHandlerService: GlobalErrorHandlerService) {
effect(() => {
const errors = this.globalErrorHandlerService.getErrorEntries()();
this.showExclamationMark = errors.length > 0;
});
}
效果很好。但errors.length总是为空,为什么? 我没有看到我错过了什么。
我在服务调试期间注意到 errorEntries 属性之一 有一个值:
SYMBOL(Signal):
value: Array(1)
包含一个值。
建议以下改进。
我们可以用
_
来定义私有变量。
private _errorEntries: WritableSignal<ErrorEntry[]> = signal<ErrorEntry[]>(
[]
);
我们可以将 getter 设为
asReadonly
信号,因为该方法似乎只修改信号。
get errorEntries(): Signal<ErrorEntry[]> {
return this._errorEntries.asReadonly();
}
那么对于您的场景,您实际上并不需要
effect
(因为它们不适用于副作用/DOM 更新),但您的场景是原始状态的派生状态。所以更好的解决方案是使用computed
来计算。
showExclamationMark = computed(() =>
this.globalErrorHandlerService.errorEntries().length > 0 ? '!' : ''
);
import {
Component,
Injectable,
inject,
WritableSignal,
signal,
Signal,
effect,
computed,
} from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
export interface ErrorEntry {
timestamp: string;
message: string;
stack: string;
route: string;
}
@Injectable({
providedIn: 'root',
})
export class GlobalErrorHandlerService {
private _errorEntries: WritableSignal<ErrorEntry[]> = signal<ErrorEntry[]>(
[]
);
get errorEntries(): Signal<ErrorEntry[]> {
return this._errorEntries.asReadonly();
}
public addError(error: any): void {
const timestamp = new Date().toISOString();
const message = error.message || error.toString();
const stack = error.stack || 'No stack trace available';
const route = '';
const errorEntry: ErrorEntry = { timestamp, message, stack, route };
this._errorEntries.update((entries) => [...entries, errorEntry]);
}
}
@Component({
selector: 'app-root',
template: `
{{showExclamationMark()}}
`,
})
export class App {
name = 'asedf';
showExclamationMark = computed(() =>
this.globalErrorHandlerService.errorEntries().length > 0 ? '!' : ''
);
constructor(private globalErrorHandlerService: GlobalErrorHandlerService) {}
ngOnInit() {
this.globalErrorHandlerService.addError(new Error('adsfasdf'));
}
}
bootstrapApplication(App);