javascript - RXJS 去抖动和修改 BehaviourSubject
问题描述
我有这个工作但是我不确定这是否是最好的方法。我觉得每个方法中应该有一个更简单的方法——addTodo、deleteTodoById、updateTodo。
我正在使用 BehaviourSubject 来修改数组,但是当我更新时,我希望消除用户输入(或延迟)并在后台更新本地存储
如何改进和简化 RXJS 代码?
import { Injectable } from "@angular/core"
import { Todo } from "./todo"
import { BehaviorSubject, Observable } from 'rxjs'
import { take } from 'rxjs/operators'
@Injectable()
export class TodoService {
todos: BehaviorSubject<Todo[]> = new BehaviorSubject<Todo[]>([]);
observable: Observable<Todo[]> = this.todos.asObservable();
getTodos(): Observable<Todo[]> {
try {
const todos: Todo[] = JSON.parse(localStorage.getItem('todos'))
if(!todos) {
return this.todos
}
this.todos.pipe(take(1)).subscribe(() => {
return this.todos.next(todos)
})
return this.todos;
} catch(err) {
console.log('have no local storage')
}
}
addTodo(todo: Todo): TodoService {
this.todos.pipe(take(1)).subscribe(todos => {
this.updateLocalStorage([...todos, todo])
return this.todos.next([...todos, todo])
})
return this
}
deleteTodoById(id): TodoService {
this.todos.pipe(take(1)).subscribe(todos => {
const filteredTodos = todos.filter(t => t.id !== id)
this.updateLocalStorage(filteredTodos)
return this.todos.next(filteredTodos)
})
return this
}
updateTodo(id, title): void {
this.todos.pipe(take(1)).subscribe((todos) => {
const todo = todos.find(t => t.id === id)
if(todo) {
todo.title = title
const newTodos = todos.map(t => (t.id === id ? todo : t))
this.updateLocalStorage(newTodos)
return this.todos.next(newTodos)
}
})
}
updateLocalStorage(todos):void {
this.todos.subscribe(t => {
setTimeout(() => {
localStorage.setItem('todos', JSON.stringify(todos))
}, 300)
})
}
}
解决方案
到目前为止,我不确定您想要改进什么。
我创建了这个 mooked 应用程序来向您展示我是如何管理这种操作的。
在这个应用程序上,我没有使用ReactiveFormModule
Angular 可以轻松抽象这部分:
const inputElement = document.getElementById('input') as HTMLInputElement;
const onChange$ = fromEvent(
inputElement, // In keyup from input field.
'keyup'
).pipe(
debounceTime(1000), // Delay the user input
map(() => inputElement.value) // Transform KeyboardEvent to input value string.
);
通过做这样的事情
<input
type="text"
name="title"
[formControl]="title"
>
export class FooComponent implement OnInit {
title: FormControl = new FormControl();
ngOnInit() {
this.title.valueChanges.pipe(debounceTime(1000)).subscribe(title => {
// Do something with your debounced data.
})
}
}
然后你可以按照这个逻辑:
export class TodoService {
private _todos$: BehaviorSubject<Todo[]>;
private _todos: Todo[];
constructor() {
this._todos = (this.hasLocalStorage())?this.getLocalStorage():[];
this._todos$ = new BehaviorSubject(this._todos);
}
add(todo: Todo) {
this._todos.push(todo);
this.refresh();
}
edit(id: number, title: string) {
// Find by id and copy current todo.
const todo = {
...this._todos.find(todo => todo.id === id)
};
// Update title
todo.title = title;
// Update todos reference
this._todos = [
// Find any other todos.
...this._todos.filter(todo => todo.id !== id),
todo
];
this.refresh();
}
get todos$(): Observable<Todo[]> {
return this._todos$.asObservable();
}
private refresh() {
this._todos$.next([...this._todos]);
localStorage.setItem('todos', JSON.stringify(this._todos));
}
private hasLocalStorage(): boolean {
return (localStorage.getItem('todos') !== null);
}
private getLocalStorage(): Todo[] {
return JSON.parse(localStorage.getItem('todos'));
}
}
1/ 这里我有 2 个属性,一个是我的商店,我将在其中保留对我所有待办事项的引用,第二个是我的 BehaviorSubject,它用于在我的商店更新时通知我的应用程序的其余部分。
2/ 在我的构造函数中,我通过空数组或 localStorage 数据(如果存在)初始化这两个属性。
3/我有refresh
做两件事的方法,更新我的两个属性。
4/ 在添加/编辑/删除操作时,我将其作为常规数组操作执行,然后我调用“刷新”。
瞧
推荐阅读
- powershell - 在命令行中使用 psexec 传递参数的 Powershell 脚本
- javascript - JavaScript:在使用 EXIF 进行移动上传之前调整图像方向
- salesforce - 用于 Salesforce 发布标注的 JSON 序列化程序
- angularjs - ng-repeat 过滤器在数据重新加载后停止工作
- vba - 四分之一循环完成后 VBA 运行时错误 1004“应用程序定义或对象定义错误”
- amazon-web-services - 无法推送到 Kubernetes 注册表
- angular - 无法显示 mat-table 内容
- opencv - Opencv:如何在图像中找到最少使用的颜色
- azure - Microsoft Bot 服务 - 设置问候消息
- php - RHEL 无法通过 PHP 代码连接 MySQL 数据库