У меня есть форма, которая выглядит примерно так:
Program Name
и Description
являются частью Реактивной формы.И Feature Image
и Video(s)
являются файловыми вводами.
У меня есть две кнопки для отправки формы: Сохранить как черновик и Опубликовать.Публикация будет включена, если заполнены все поля, включая оба файла.Сохранить как черновик всегда включено и отправит форму.
При отправке формы: Я проверяю, есть ли изображение компонента.Если он есть, я загружаю его в хранилище Firebase.Я применяю ту же проверку для видео.Если есть / есть какие-либо видео, я загружаю их одно за другим в корзину хранения Firebase.Вот код для того же самого:
let featureImageUrl$: Observable<string>;
const videoUrls$: Observable<string>[] = [];
// Check if featureImageToUpload was uploaded
if (this.featureImageToUpload) {
featureImageUrl$ = this.fileService.upload(`content/programs/images/${this.utils.generateRandomString()}`, this.featureImageToUpload);
}
// Check if video(s) was/were uploaded
if (this.videosToUpload) {
this.utils.range(this.videosToUpload.length).forEach(fileIndex => {
// tslint:disable-next-line:max-line-length
const videoUrl$ = this.fileService.upload(`content/programs/videos/${this.utils.generateRandomString()}`, this.videosToUpload[fileIndex]);
videoUrls$.push(videoUrl$);
});
}
this.fileService.upload
- это всего лишь метод, который возвращает Observable<string>
, по существу упаковывая URL-адрес загрузки файла, который был загружен.
this.utils.range
это просто метод, который возвращает массив чисел на основе длины.так что если длина равна 4, то она вернет [0, 1, 2, 3]
Проблема:
Я хочу создать Observable
, на который я могу подписаться, чтобы получить Объект со структуройвот так:
{
featureImageUrl: 'DOWNLOAD URL FOR THE FEATURE IMAGE' || null // null in case the file wasn't uploaded;
videos: [
'DOWNLOAD URL FOR VIDEO 1',
'DOWNLOAD URL FOR VIDEO 2',
'DOWNLOAD URL FOR VIDEO 3',
'DOWNLOAD URL FOR VIDEO 4',
...
] || null // null in case the video(s) were not uploaded;
}
Вещи, которые я пробовал до сих пор:
Я мог бы использовать forkJoin
вот так:
forkJoin(...videoUrls$, featureImageUrl$)
.subscribe(downloadUrls => {
console.log(downloadUrls);
});
А затем извлечь видео скачатьURL, основанные на длине videoUrls$
, а затем создайте мой объект соответственно.Но я ищу более чистый способ сделать это.
Я также пытался использовать Observable.create
, но не смог обернуть его вокруг этого конкретного случая использования.
С предложениями от Buggy я также попробовал это:
forkJoin(forkJoin(videoUrls$), featureImageUrl$)
.pipe(
map(([videoUrls, featureImageUrl]) => ({videoUrls, featureImageUrl}))
);
Он отлично работает в случае, если выбраны функция изображения и видео.Но если я просто выберу Feature Image, а не выберу ни одного видео, подписка никогда не достигнет.
Вот вам Пример StackBlitz для справки.