javascript - RXJS 去抖并修改BehaviorSubject

标签 javascript angular rxjs

我有这个工作,但是我不确定这是否是最好的方法。我觉得每个方法都应该有一个更简单的方法 - 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 应用程序来向您展示我如何管理此类操作。

在此应用程序中,我没有使用 Angular 中的 ReactiveFormModule ,它可以轻松抽象这部分:

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/在添加/编辑/删除操作中,我将其作为常规数组操作执行,然后调用“刷新”。

live coding

关于javascript - RXJS 去抖并修改BehaviorSubject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55566610/

相关文章:

javascript - 如何在javascript中为位置绝对元素设置边界

javascript - 如何使用 JavaScript 解析带有双大括号的字符串?

css - Angular 5 : fade animation during routing (CSS)

angular - 设置值后不显示自动完成

javascript - 如果 observable 使用异步管道是错误的,则 Angular 显示模板

Angular *ngIf 多次调用,使用异步管道和订阅

javascript - 如何通过 JavaScript 将 XML 发布到 REST API?

javascript - cryptojs 和 golang 给出不同的 sha3 哈希值

html - Ag 网格,防止表格缩放到全宽

javascript - Rx.Observable.prototype.skip 未定义