Просмотр исходного кода

fix(web): remove dependency on rxjs (#3301)

The dependency on rxjs has been removed in favour of iterators as it's clearer
and the nature of the workload is inherently non-reactive. The uncaught error
when the list of files is empty has also been implicitly fixed by this change.

Fixes: #3300
Thomas 2 лет назад
Родитель
Сommit
8045fd3f14
3 измененных файлов с 33 добавлено и 33 удалено
  1. 4 19
      web/package-lock.json
  2. 0 1
      web/package.json
  3. 29 13
      web/src/lib/utils/file-uploader.ts

+ 4 - 19
web/package-lock.json

@@ -19,7 +19,6 @@
         "leaflet.markercluster": "^1.5.3",
         "lodash-es": "^4.17.21",
         "luxon": "^3.2.1",
-        "rxjs": "^7.8.0",
         "socket.io-client": "^4.6.1",
         "svelte-local-storage-store": "^0.5.0",
         "svelte-material-icons": "^3.0.5",
@@ -10526,14 +10525,6 @@
         "queue-microtask": "^1.2.2"
       }
     },
-    "node_modules/rxjs": {
-      "version": "7.8.1",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
-      "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
-      "dependencies": {
-        "tslib": "^2.1.0"
-      }
-    },
     "node_modules/sade": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
@@ -11447,7 +11438,8 @@
     "node_modules/tslib": {
       "version": "2.5.3",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
-      "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w=="
+      "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
+      "dev": true
     },
     "node_modules/tsutils": {
       "version": "3.21.0",
@@ -19522,14 +19514,6 @@
         "queue-microtask": "^1.2.2"
       }
     },
-    "rxjs": {
-      "version": "7.8.1",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
-      "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
-      "requires": {
-        "tslib": "^2.1.0"
-      }
-    },
     "sade": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
@@ -20184,7 +20168,8 @@
     "tslib": {
       "version": "2.5.3",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
-      "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w=="
+      "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
+      "dev": true
     },
     "tsutils": {
       "version": "3.21.0",

+ 0 - 1
web/package.json

@@ -70,7 +70,6 @@
     "leaflet.markercluster": "^1.5.3",
     "lodash-es": "^4.17.21",
     "luxon": "^3.2.1",
-    "rxjs": "^7.8.0",
     "socket.io-client": "^4.6.1",
     "svelte-local-storage-store": "^0.5.0",
     "svelte-material-icons": "^3.0.5",

+ 29 - 13
web/src/lib/utils/file-uploader.ts

@@ -1,8 +1,7 @@
 import { uploadAssetsStore } from '$lib/stores/upload';
-import { addAssetsToAlbum, getFilenameExtension } from '$lib/utils/asset-utils';
+import { addAssetsToAlbum } from '$lib/utils/asset-utils';
 import type { AssetFileUploadResponseDto } from '@api';
 import axios from 'axios';
-import { combineLatestAll, filter, firstValueFrom, from, mergeMap, of } from 'rxjs';
 import { notificationController, NotificationType } from './../components/shared-components/notification/notification';
 
 const extensions = [
@@ -70,9 +69,9 @@ export const openFileUploadDialog = async (
         if (!target.files) {
           return;
         }
-        const files = Array.from<File>(target.files);
+        const files = Array.from(target.files);
 
-        resolve(await fileUploadHandler(files, albumId, sharedKey));
+        resolve(fileUploadHandler(files, albumId, sharedKey));
       };
 
       fileSelector.click();
@@ -88,16 +87,33 @@ export const fileUploadHandler = async (
   albumId: string | undefined = undefined,
   sharedKey: string | undefined = undefined,
 ) => {
-  return firstValueFrom(
-    from(files).pipe(
-      filter((file) => extensions.includes('.' + getFilenameExtension(file.name))),
-      mergeMap(async (file) => of(await fileUploader(file, albumId, sharedKey)), 2),
-      combineLatestAll(),
-    ),
-  );
+  const iterable = {
+    files: files.filter((file) => extensions.some((ext) => file.name.endsWith(ext)))[Symbol.iterator](),
+
+    async *[Symbol.asyncIterator]() {
+      for (const file of this.files) {
+        yield fileUploader(file, albumId, sharedKey);
+      }
+    },
+  };
+
+  const concurrency = 2;
+  // TODO: use Array.fromAsync instead when it's available universally.
+  return Promise.all([...Array(concurrency)].map(() => fromAsync(iterable))).then((res) => res.flat());
+};
+
+// polyfill for Array.fromAsync.
+//
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fromAsync
+const fromAsync = async function <T>(iterable: AsyncIterable<T>) {
+  const result = [];
+  for await (const value of iterable) {
+    result.push(value);
+  }
+  return result;
 };
 
-//TODO: should probably use the @api SDK
+// TODO: should probably use the @api SDK
 async function fileUploader(
   asset: File,
   albumId: string | undefined = undefined,
@@ -122,7 +138,7 @@ async function fileUploader(
       progress: 0,
     });
 
-    const response = await axios.post(`/api/asset/upload`, formData, {
+    const response = await axios.post('/api/asset/upload', formData, {
       params: {
         key: sharedKey,
       },