async-preloader
    Preparing search index...

    async-preloader

    async-preloader

    npm version stability-stable npm minzipped size dependencies types Conventional Commits styled with prettier linted with eslint tested with jest license

    Assets preloader using async/await and fetch for usage both in the browser and Node.js.

    paypal coinbase twitter

    npm install --save async-preloader
    

    This section covers the basic usage of AsyncPreloader. For more informations about async/await, see Async functions - making promises friendly. Usage in Node.js environment is limited to its capacity to handle fetch requests and DOM APIs. Polyfills like undici/node-fetch (for Node.js below 18) and xmldom might come handy .

    import AsyncPreloader from "async-preloader";

    const items = [
    { id: "myDefaultFile", src: "assets/default" },
    { id: "myTextFile", src: "assets/text.txt" },
    { id: "myJsonFile", src: "assets/json.json" },
    { id: "myImageFile", src: "assets/image.jpg" },
    { id: "myVideoFile", src: "assets/video.mp4" },
    { id: "myAudioFile", src: "assets/audio.mp3" },
    { id: "myXmlFile", src: "assets/xml.xml" },
    { id: "mySvgFile", src: "assets/xml.svg" },
    { id: "myHtmlFile", src: "assets/xml.html" },
    { id: "myDefaultXmlFile", src: "assets/xml", loader: "Xml" },
    { id: "myFont", src: `assets/font.ttf` },
    { id: "Space Regular", loader: "Font", fontOptions: { timeout: 10000 } },
    // Can be retrieved with the src property eg. AsyncPreloader.items.get("assets/fileWithoutId")
    { src: "assets/fileWithoutId" },
    ];

    // Pass an array of LoadItem
    //
    // Returns a Promise with an array of LoadedValue
    const pItems = AsyncPreloader.loadItems(items);

    pItems
    .then((items) => {
    const element = AsyncPreloader.items.get("myVideoFile");
    document.body.appendChild(element);
    })
    .catch((error) => console.error("Error loading items", error));

    Note: Font loader will try to detect the font in the page using FontFaceObserver when no src is specified.

    It works in a similar fashion as createjs's PreloadJS.

    import AsyncPreloader from "async-preloader";

    // Pass the file url and an optional path of the property to get in the JSON file.
    // It will load the file using the Json loader and look for the path key expecting an array of `LoadItem`s.
    // Default path is "items" eg the default manifest would look like this:
    // `{ "items": [ { "src": "assets/file1" }, { "src": "assets/file2" }] }`
    //
    // Returns a Promise with an array of LoadedValue
    const pItems = AsyncPreloader.loadManifest(
    "assets/manifest.json",
    "data.preloader.items"
    );

    pItems
    .then((items) => useLoadedItemsFromManifest(items)) // or AsyncPreloader.items.get("src or id")
    .catch((error) => console.error("Error loading items", error));

    This section takes a closer look at the options of AsyncPreloader.

    import AsyncPreloader from "async-preloader";

    // Pass a LoadItem
    //
    // Returns a Promise with the LoadedValue
    const pItem = AsyncPreloader.loadJson({ src: "assets/json.json" });

    pItem
    .then((item) => useLoadedItem(item))
    .catch((error) => console.error("Error loading item", error));

    Note: Using the loaders directly won't add the item to the items Map. Alternatively you could use AsyncPreloader.loadItem and rely on the file extension or add { loader: "Json"} to the item.

    import AsyncPreloader from "async-preloader";

    try {
    // Pass a string
    //
    // Returns a Promise with the LoadedValue
    const pItem = await AsyncPreloader.loadItem("assets/json.json");
    } catch (error) {
    console.error(error);
    }

    You can specify how the response is handle by using the body key in a LoadItem.

    Typical use case: get an ArrayBuffer for the WebAudio API to decode the data with baseAudioContext.decodeAudioData().

    import AsyncPreloader from "async-preloader";

    const audioContext = new AudioContext();
    const pItem = AsyncPreloader.loadAudio({
    src: "assets/audio.mp3",
    body: "arrayBuffer",
    });

    pItem
    .then((item) => audioContext.decodeAudioData(item))
    .then((decodedData) => useDecodedData(decodedData))
    .catch((error) => console.error("Error decoding audio", error));

    Since fetch doesn't support Progress events yet, you might want to get a per file progress.

    import AsyncPreloader from "async-preloader";

    const items = [
    { id: "myDefaultFile", src: "assets/default" }, // ...
    ];

    let loadedCount = 0;

    async function preload() {
    await Promise.all(
    items.map(async (item) => {
    const data = await AsyncPreloader.loadItem(item);
    loadedCount++;
    console.log(`Progress: ${(100 * loadedCount) / items.length}%`);
    })
    );
    }

    await preload();

    To abort a loadItem(s) call, you can create an AbortController instance and pass its signal to options.

    const controller = new AbortController();

    const timeoutId = setTimeout(() => {
    controller.abort();
    }, 150);

    try {
    await AsyncPreloader.loadItems(
    items.map((item) => ({
    ...item,
    options: { ...(item.options || {}), signal: controller.signal },
    }))
    );
    } catch (error) {
    if (error.name === "AbortError") console.log("Request was aborted");
    } finally {
    clearTimeout(timeoutId);
    }

    MIT © Damien Seguin