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.info('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)
      })
  }
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
1 313
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

я не уверен в том, что вы хотите улучшить до сих пор.

Я создал это приложение, чтобы показать вам, как я управляю такого рода операциями.

В этом приложении я не использовал 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, который делает 2 вещи, обновляет оба моих свойства.

4/ При операции добавления/редактирования/удаления я выполняю ее как обычную операцию с массивом, затем вызываю «обновить».

вуаля

живое кодирование

Спасибо - это в значительной степени подтверждает некоторые мои мысли - мне нужно прикрепить наблюдатель событий к элементу, если я хочу отменить ввод.

Ruegen 08.04.2019 11:51

Я настоятельно рекомендую вам использовать ReactiveFormModule из angular, который делает то же самое, но с высоким уровнем абстракции. Нравится FormControl раздел моего ответа.

Yanis-git 08.04.2019 12:15

Другие вопросы по теме