{"id":20767749,"url":"https://github.com/dmnsgn/async-preloader","last_synced_at":"2025-04-05T23:12:05.400Z","repository":{"id":23729021,"uuid":"99706957","full_name":"dmnsgn/async-preloader","owner":"dmnsgn","description":"Assets preloader using async/await and fetch for usage both in the browser and Node.js.","archived":false,"fork":false,"pushed_at":"2025-03-28T08:52:00.000Z","size":11553,"stargazers_count":62,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-29T20:09:11.748Z","etag":null,"topics":["async","async-await","es2017","fetch","preloader","typescript"],"latest_commit_sha":null,"homepage":"https://dmnsgn.github.io/async-preloader/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dmnsgn.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":["https://paypal.me/dmnsgn","https://commerce.coinbase.com/checkout/56cbdf28-e323-48d8-9c98-7019e72c97f3"]}},"created_at":"2017-08-08T15:18:05.000Z","updated_at":"2024-10-09T15:01:15.000Z","dependencies_parsed_at":"2024-06-18T22:40:54.158Z","dependency_job_id":"0c6b5790-8a16-46d9-8562-f5f9d59f536d","html_url":"https://github.com/dmnsgn/async-preloader","commit_stats":{"total_commits":225,"total_committers":6,"mean_commits":37.5,"dds":0.3244444444444444,"last_synced_commit":"c1a85109afec2a2500fc29044601caef31825333"},"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmnsgn%2Fasync-preloader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmnsgn%2Fasync-preloader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmnsgn%2Fasync-preloader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmnsgn%2Fasync-preloader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dmnsgn","download_url":"https://codeload.github.com/dmnsgn/async-preloader/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247411239,"owners_count":20934653,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","async-await","es2017","fetch","preloader","typescript"],"created_at":"2024-11-17T11:33:15.120Z","updated_at":"2025-04-05T23:12:05.384Z","avatar_url":"https://github.com/dmnsgn.png","language":"JavaScript","readme":"# async-preloader\n\n[![npm version](https://img.shields.io/npm/v/async-preloader)](https://www.npmjs.com/package/async-preloader)\n[![stability-stable](https://img.shields.io/badge/stability-stable-green.svg)](https://www.npmjs.com/package/async-preloader)\n[![npm minzipped size](https://img.shields.io/bundlephobia/minzip/async-preloader)](https://bundlephobia.com/package/async-preloader)\n[![dependencies](https://img.shields.io/librariesio/release/npm/async-preloader)](https://github.com/dmnsgn/async-preloader/blob/main/package.json)\n[![types](https://img.shields.io/npm/types/async-preloader)](https://github.com/microsoft/TypeScript)\n[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-fa6673.svg)](https://conventionalcommits.org)\n[![styled with prettier](https://img.shields.io/badge/styled_with-Prettier-f8bc45.svg?logo=prettier)](https://github.com/prettier/prettier)\n[![linted with eslint](https://img.shields.io/badge/linted_with-ES_Lint-4B32C3.svg?logo=eslint)](https://github.com/eslint/eslint)\n[![tested with jest](https://img.shields.io/badge/tested_with-jest-99424f.svg)](https://github.com/facebook/jest)\n[![license](https://img.shields.io/github/license/dmnsgn/async-preloader)](https://github.com/dmnsgn/async-preloader/blob/main/LICENSE.md)\n\nAssets preloader using async/await and fetch for usage both in the browser and Node.js.\n\n[![paypal](https://img.shields.io/badge/donate-paypal-informational?logo=paypal)](https://paypal.me/dmnsgn)\n[![coinbase](https://img.shields.io/badge/donate-coinbase-informational?logo=coinbase)](https://commerce.coinbase.com/checkout/56cbdf28-e323-48d8-9c98-7019e72c97f3)\n[![twitter](https://img.shields.io/twitter/follow/dmnsgn?style=social)](https://twitter.com/dmnsgn)\n\n## Install\n\n```bash\nnpm install --save async-preloader\n```\n\n## Documentation\n\n- [AsyncPreloader class](https://dmnsgn.github.io/async-preloader/classes/index.AsyncPreloader.html)\n- [AsyncPreloader types](https://dmnsgn.github.io/async-preloader/modules/types.html)\n\n## Quick start\n\nThis section covers the basic usage of `AsyncPreloader`. For more informations about async/await, see [Async functions - making promises friendly](https://developers.google.com/web/fundamentals/primers/async-functions). Usage in Node.js environment is limited to its capacity to handle `fetch` requests and DOM APIs. Polyfills like [`undici`](https://www.npmjs.com/package/undici/)/[`node-fetch`](https://www.npmjs.com/package/node-fetch) (for Node.js below 18) and [`xmldom`](https://www.npmjs.com/package/xmldom) might come handy .\n\n### Preload items and retrieve them\n\n```javascript\nimport AsyncPreloader from \"async-preloader\";\n\nconst items = [\n  { id: \"myDefaultFile\", src: \"assets/default\" },\n  { id: \"myTextFile\", src: \"assets/text.txt\" },\n  { id: \"myJsonFile\", src: \"assets/json.json\" },\n  { id: \"myImageFile\", src: \"assets/image.jpg\" },\n  { id: \"myVideoFile\", src: \"assets/video.mp4\" },\n  { id: \"myAudioFile\", src: \"assets/audio.mp3\" },\n  { id: \"myXmlFile\", src: \"assets/xml.xml\" },\n  { id: \"mySvgFile\", src: \"assets/xml.svg\" },\n  { id: \"myHtmlFile\", src: \"assets/xml.html\" },\n  { id: \"myDefaultXmlFile\", src: \"assets/xml\", loader: \"Xml\" },\n  { id: \"myFont\", src: `assets/font.ttf` },\n  { id: \"Space Regular\", loader: \"Font\", fontOptions: { timeout: 10000 } },\n  // Can be retrieved with the src property eg. AsyncPreloader.items.get(\"assets/fileWithoutId\")\n  { src: \"assets/fileWithoutId\" },\n];\n\n// Pass an array of LoadItem\n//\n// Returns a Promise with an array of LoadedValue\nconst pItems = AsyncPreloader.loadItems(items);\n\npItems\n  .then((items) =\u003e {\n    const element = AsyncPreloader.items.get(\"myVideoFile\");\n    document.body.appendChild(element);\n  })\n  .catch((error) =\u003e console.error(\"Error loading items\", error));\n```\n\n---\n\nNote: Font loader will try to detect the font in the page using [FontFaceObserver](https://github.com/dmnsgn/fontfaceobserver) when no src is specified.\n\n### Load items from a manifest file\n\nIt works in a similar fashion as createjs's [PreloadJS](http://www.createjs.com/docs/preloadjs/classes/LoadQueue.html).\n\n```javascript\nimport AsyncPreloader from \"async-preloader\";\n\n// Pass the file url and an optional path of the property to get in the JSON file.\n// It will load the file using the Json loader and look for the path key expecting an array of `LoadItem`s.\n// Default path is \"items\" eg the default manifest would look like this:\n// `{ \"items\": [ { \"src\": \"assets/file1\" }, { \"src\": \"assets/file2\" }] }`\n//\n// Returns a Promise with an array of LoadedValue\nconst pItems = AsyncPreloader.loadManifest(\n  \"assets/manifest.json\",\n  \"data.preloader.items\"\n);\n\npItems\n  .then((items) =\u003e useLoadedItemsFromManifest(items)) // or AsyncPreloader.items.get(\"src or id\")\n  .catch((error) =\u003e console.error(\"Error loading items\", error));\n```\n\n## Advanced usage\n\nThis section takes a closer look at the options of `AsyncPreloader`.\n\n### Load a single item by using the [loaders](https://github.com/dmnsgn/async-preloader/blob/main/src/index.ts#L60) directly\n\n```javascript\nimport AsyncPreloader from \"async-preloader\";\n\n// Pass a LoadItem\n//\n// Returns a Promise with the LoadedValue\nconst pItem = AsyncPreloader.loadJson({ src: \"assets/json.json\" });\n\npItem\n  .then((item) =\u003e useLoadedItem(item))\n  .catch((error) =\u003e console.error(\"Error loading item\", error));\n```\n\n---\n\nNote: Using the loaders directly won't add the item to the `items` Map.\nAlternatively you could use `AsyncPreloader.loadItem` and rely on the file extension or add `{ loader: \"Json\"}` to the item.\n\n### Load a single item by using a string directly\n\n```javascript\nimport AsyncPreloader from \"async-preloader\";\n\ntry {\n  // Pass a string\n  //\n  // Returns a Promise with the LoadedValue\n  const pItem = await AsyncPreloader.loadItem(\"assets/json.json\");\n} catch (error) {\n  console.error(error);\n}\n```\n\n### Get an `ArrayBuffer` instead of the default `Blob`\n\nYou can specify how the response is handle by using the `body` key in a `LoadItem`.\n\nTypical use case: get an ArrayBuffer for the WebAudio API to decode the data with `baseAudioContext.decodeAudioData()`.\n\n```javascript\nimport AsyncPreloader from \"async-preloader\";\n\nconst audioContext = new AudioContext();\nconst pItem = AsyncPreloader.loadAudio({\n  src: \"assets/audio.mp3\",\n  body: \"arrayBuffer\",\n});\n\npItem\n  .then((item) =\u003e audioContext.decodeAudioData(item))\n  .then((decodedData) =\u003e useDecodedData(decodedData))\n  .catch((error) =\u003e console.error(\"Error decoding audio\", error));\n```\n\n### Getting the progress\n\nSince `fetch` doesn't support `Progress events` yet, you might want to get a per file progress.\n\n```javascript\nimport AsyncPreloader from \"async-preloader\";\n\nconst items = [\n  { id: \"myDefaultFile\", src: \"assets/default\" }, // ...\n];\n\nlet loadedCount = 0;\n\nasync function preload() {\n  await Promise.all(\n    items.map(async (item) =\u003e {\n      const data = await AsyncPreloader.loadItem(item);\n      loadedCount++;\n      console.log(`Progress: ${(100 * loadedCount) / items.length}%`);\n    })\n  );\n}\n\nawait preload();\n```\n\n### Abort one or more loadItem(s) request(s)\n\nTo abort a loadItem(s) call, you can create an `AbortController` instance and pass its signal to options.\n\n```javascript\nconst controller = new AbortController();\n\nconst timeoutId = setTimeout(() =\u003e {\n  controller.abort();\n}, 150);\n\ntry {\n  await AsyncPreloader.loadItems(\n    items.map((item) =\u003e ({\n      ...item,\n      options: { ...(item.options || {}), signal: controller.signal },\n    }))\n  );\n} catch (error) {\n  if (error.name === \"AbortError\") console.log(\"Request was aborted\");\n} finally {\n  clearTimeout(timeoutId);\n}\n```\n\n## License\n\nMIT © [Damien Seguin](https://github.com/dmnsgn)\n","funding_links":["https://paypal.me/dmnsgn","https://commerce.coinbase.com/checkout/56cbdf28-e323-48d8-9c98-7019e72c97f3"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmnsgn%2Fasync-preloader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdmnsgn%2Fasync-preloader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmnsgn%2Fasync-preloader/lists"}