В Rxjs является ли это анти-паттерном, если вы добавляете значение в массив, а затем сразу после этого выделяете массив как наблюдаемый? - PullRequest
1 голос
/ 26 мая 2019

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

Мой файл component.ts имеет следующие свойства:

uploadPicturesSubject$: Subject<any[]> = new Subject<any[]>();
  previewUrls$: Observable<any[]> = this.uploadPicturesSubject$.asObservable();
  previewUrls: any[] = [];

Тогда в моем обработчике события (изменения) (когда пользователь загружает фотографии) у меня есть следующий код:

...
const reader: FileReader = new FileReader();
      reader.readAsDataURL(uploadPicture.file);
      reader.onload = (event: any) => {        
        this.previewUrls.push(event.target.result)
        this.uploadPicturesSubject$.next(this.previewUrls);
      };

В моем шаблоне я использую асинхронный канал для подписки на previewUrls $ observable, и все работает как положено. Я не был уверен, было ли добавление src загруженного изображения со строкой this.previewUrls.push(event.target.result) и последующее выделение массива this.uploadPicturesSubject$.next(this.previewUrls); антипаттерном или нет, потому что казалось, что таким образом было больше кода, чем просто в шаблоне html делает цикл *ngFor для массива this.previewUrls, так как он достигает того же результата.

Спасибо за понимание.

1 Ответ

2 голосов
/ 26 мая 2019

Для меня смешивание реактивных паттернов (субъектов, наблюдаемых) с другими паттернами, в которых состояние хранится в локальных переменных, выглядит как анти-паттерн.

Чтобы предотвратить это, я бы выбрал другой подход:

Я бы начал с темы предмета uploadPicture (было бы здорово, если бы я набрал текст, чтобы избежать 'any'). Идея в том, что за один раз в нее попадает только одна картинка.

uploadPicture = new Subject<any>();

Тогда я бы настроил еще одну наблюдаемую, которая подключается к этой теме uploadPicture:

previewUrls$ = uploadPicture.pipe(
    scan((pictures, newPicture) => pictures.concat(newPicture), [])
)

Что хорошо в сканировании, оно генерирует каждый раз, когда значение приходит. Для меня (и недавний твит Бен Леш подтвердил это), это один из самых мощных операторов в RxJS.

Таким образом, каждый раз, когда появляется новое изображение, вы просто следующий на тему uploadPicture:

this.uploadPicture.next(event.target.result)

и весь массив, включая новое изображение, будет генерироваться из previewUrls $.

Отсюда вы можете просто асинхронизировать канал previewUrls$ и получить тот же результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...