Estoy usando el archivo Arrastrar y soltar para cargar varias imágenes.
Cómo usar con async esperar para cargar imágenes porque quiero enviar parámetros a la siguiente imagen devuelta desde la primera solicitud.
post_id devuelto desde la primera solicitud debe enviarse con todas las imágenes siguientes.
esto es lo que estoy haciendo pero no estoy esperando:
dropped(files: NgxFileDropEntry[]) { this.files = files; for (const droppedFile of files) { // Is it a file? if (droppedFile.fileEntry.isFile) { const fileEntry = droppedFile.fileEntry as FileSystemFileEntry; fileEntry.file(async (file: File) => { // Here you can access the real file console.log(droppedFile.relativePath, file); await new Promise((resolve, reject) => { this.http.uploadImages(file, 'UploadImage', this.postId).subscribe((res: any) => { if (res.status == true) { resolve(true); this.postId = res.data.post_id; // i want to send this ID in next request. } else { reject(); console.log(res.message); } }) }); }); } else { // It was a directory (empty directories are added, otherwise only files) const fileEntry = droppedFile.fileEntry as FileSystemDirectoryEntry; console.log(droppedFile.relativePath, fileEntry); } } }[Puedes usar este rasgo:
public paramsArray = [ { param1: '1', param2: 2 }, { param1: '3', param2: 4 } ] public subject: BehaviorSubject<any> = new BehaviorSubject<null>; construnctor() { this.subject.asObservable().subscribe((value) => { if (value) { this.http.uploadImage(value).subscribe((res) => { if (this.paramsArray.length) { this.subject.next(paramsArray.splice(0, 1)[0]); } }); } }); } startUploading() { this.subject.next(this.paramsArray.splice(0, 1)[0]); }Comenzará desde el índice 0 de paramsArray y los cargará uno tras otro.
Supongo que para la primera foto que se va a subir, tienes un postId almacenado en la variable this.postId . Usaremos esa para cargar la primera foto y luego introduciremos una segunda variable para contener el post_id devuelto por el método de carga.
Usamos Observable en lugar de Promise porque, como todos sabemos, las promesas se ejecutarán sin importar el momento en que las instanciamos, que no es lo que queremos. También estamos usando concat para asegurarnos de que todos los archivos se carguen uno por uno.
private photoPostId: number | null = null; dropped(files: NgxFileDropEntry[]) { this.files = files; const tasks = files.map((droppedFile) => { return new Observable<number>((subscriber) => { if (droppedFile.fileEntry.isFile) { const fileEntry = droppedFile.fileEntry as FileSystemFileEntry; fileEntry.file(async (file: File) => { // Here you can access the real file console.log(droppedFile.relativePath, file); this.http .uploadImages( file, 'UploadImage', this.photoPostId ?? this.postId ) .subscribe((res: any) => { if (res.status == true) { subscriber.next(res.data.post_id); // i want to send this ID in next request. } }); }); } else { // It was a directory (empty directories are added, otherwise only files) const fileEntry = droppedFile.fileEntry as FileSystemDirectoryEntry; console.log(droppedFile.relativePath, fileEntry); } subscriber.complete(); }); }); concat(...tasks).subscribe((postId) => { this.photoPostId = postId; }); }En caso de que esté buscando una solución sobre cómo obtener el archivo usando Ngx-file-drop, esta es la solución que funcionó para mí.
pseudocódigo
droppedItemsCódigo
dropped(files: NgxFileDropEntry[]) { const droppedFileList = files.filter((droppedFile) => droppedFile.fileEntry.isFile); const subscription = new Subscription(); subscription.add( from([droppedFileList]) .pipe( switchMap((array) => { console.log('array', array); const result = array?.map((droppedFile) => { const fileEntry = droppedFile.fileEntry as FileSystemFileEntry; const promise = new Promise((res) => { fileEntry.file((file) => res(file)); }) return from(promise); }) return forkJoin(result); }) ) .subscribe({ next: (fileList) => console.log('fileList',fileList), error:(err)=> console.error(err) complete: () => subscription.unsubscribe() }); } **For API calls** dropped(files: NgxFileDropEntry[]) { const droppedFileList = files.filter((droppedFile) => droppedFile.fileEntry.isFile); const subscription = new Subscription(); subscription.add( from([droppedFileList]) .pipe( switchMap((array) => { console.log('array', array); const result = array?.map((droppedFile) => { const fileEntry = droppedFile.fileEntry as FileSystemFileEntry; const promise = new Promise((res) => { fileEntry.file((file) => res(file)); }) return from(promise); }) return forkJoin(result); }), switchMap((fileList) => apiFn(fileList)) ) .subscribe({ next: (resp) => console.log('resp',resp), error:(err)=> console.error(err) complete: () => subscription.unsubscribe() }); } apiFn(result){ const calls = result.map(file => apiServiceFn(file)); return forkJoin([...calls]); }Puede saber más sobre ForkJoin aquí: https://rxjs.dev/api/index/function/forkJoin
Aquí hay una aplicación Stackblitz que puede servir como base https://stackblitz.com/edit/angular-ivy-osb6kk?file=src/app/app.component.ts