Я хочу запустить действие только один раз, когда изменится условие (на true
), например.
areAllDetailsLoaded() => run a function
Я думал закодировать это как сигнал типа
areAllDetailsLoaded=signal(false);
и используя его как
effect( () => {
if (areAllDetailsLoaded()) {
storage().getDetails() ....... run code
Проблема, с которой я столкнулся, заключается в том, что, очевидно, сигнал storage
также учитывается, и каждый раз, когда storage()
изменяется, запускается код. Это не то, чего я хочу. После замены areAllDetailsLoaded
на true
код должен запускаться только один раз.
Честно говоря, у меня заканчиваются идеи. Или, возможно, мое понимание угловых сигналов недостаточно хорошее. Поэтому будет полезен шаблон шаблона котла, который лучше всего подходит для Signals.
Вот два подхода к достижению желаемого:
Использование частного флага с крючком жизненного цикла ngOnChanges
Использование BehaviorSubject из RxJS
Я нашел несколько очень хороших наблюдений.
Только считывание сигнала на верхнем уровне запускает эффект, не уверен, что это специально.
Эффект возвращает ссылку со свойством уничтожения, позволяющим уничтожить эффект и убедиться, что сигнал выполняется только один раз.
Полный код:
import { Component, effect, signal } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
@Component({
selector: 'app-root',
standalone: true,
template: `
<button (click) = "areAllDetailsLoaded.set(true)">areAllDetailsLoaded set true</button>
`,
})
export class App {
areAllDetailsLoaded = signal(false);
storage = signal(false);
name = 'Angular';
constructor() {
const effectRef = effect(() => {
console.info('effect runs');
// const storage1 = this.storage(); // un comment this to see the effect running for each change of storage
if (this.areAllDetailsLoaded()) {
const storage = this.storage();
console.info('code runs');
effectRef?.destroy();
}
});
}
ngOnInit() {
setInterval(() => {
this.storage.set(!this.storage());
console.info('interval', this.storage());
}, 1000);
}
}
bootstrapApplication(App);
Это очень хороший подход и очень хорошая модель. Спасибо, это спасает мой день :-)