diff --git a/README.md b/README.md index 5d3b1fc..5b284b3 100755 --- a/README.md +++ b/README.md @@ -55,6 +55,24 @@ console.log(text); ## Functions
+
fetchText(url, options)Promise.<string>
+

Load an item and parse the Response as text

+
+
fetchJson(url, options)Promise.<JSON>
+

Load an item and parse the Response as json

+
+
fetchArrayBuffer(url, options)Promise.<ArrayBuffer>
+

Load an item and parse the Response as arrayBuffer

+
+
fetchBlob(url, options)Promise.<Blob>
+

Load an item and parse the Response as blob

+
+
fetchImage(urlOrOpts, options)Promise.<HTMLImageElement>
+

Load an item, parse the Response as blob and create a HTML Image

+
+
fetchAll(resources)Promise.<Object.<string, LoadedResource>>
+

Loads resources from a named map

+
load(resources, callback)Promise.<Object.<string, LoadedResource>> | undefined

Loads resources from a named map

@@ -93,6 +111,102 @@ console.log(text);
+ + +## fetchText(url, options) ⇒ Promise.<string> + +Load an item and parse the Response as text + +**Kind**: global function + +| Param | Type | +| ------- | ------------------------ | +| url | RequestInfo | +| options | RequestInit | + + + +## fetchJson(url, options) ⇒ Promise.<JSON> + +Load an item and parse the Response as json + +**Kind**: global function + +| Param | Type | +| ------- | ------------------------ | +| url | RequestInfo | +| options | RequestInit | + + + +## fetchArrayBuffer(url, options) ⇒ Promise.<ArrayBuffer> + +Load an item and parse the Response as arrayBuffer + +**Kind**: global function + +| Param | Type | +| ------- | ------------------------ | +| url | RequestInfo | +| options | RequestInit | + + + +## fetchBlob(url, options) ⇒ Promise.<Blob> + +Load an item and parse the Response as blob + +**Kind**: global function + +| Param | Type | +| ------- | ------------------------ | +| url | RequestInfo | +| options | RequestInit | + + + +## fetchImage(urlOrOpts, options) ⇒ Promise.<HTMLImageElement> + +Load an item, parse the Response as blob and create a HTML Image + +**Kind**: global function + +| Param | Type | +| --------- | ----------------------------------------------------------------- | +| urlOrOpts | string \| [ImageOptions](#ImageOptions) | +| options | RequestInit | + + + +## fetchAll(resources) ⇒ Promise.<Object.<string, LoadedResource>> + +Loads resources from a named map + +**Kind**: global function + +| Param | Type | +| --------- | -------------------------------------------- | +| resources | Object.<string, Resource> | + +**Example** + +```js +const resources = { + hello: { text: "assets/hello.txt" }, + data: { json: "assets/data.json" }, + img: { image: "assets/tex.jpg" }, + hdrImg: { binary: "assets/tex.hdr" }, + blob: { binary: "assets/blob" }, +}; + +const res = await io.fetchAll(resources); +res.hello; // => DOMString +res.data; // => Object +res.img; // => HTMLImageElement +res.hdrImg; // => ArrayBuffer +res.blob; // => Blob +``` + ## load(resources, callback) ⇒ Promise.<Object.<string, LoadedResource>> \| undefined diff --git a/fetch.js b/fetch.js new file mode 100644 index 0000000..6ebb234 --- /dev/null +++ b/fetch.js @@ -0,0 +1,130 @@ +/** + * Load an item and parse the Response as text + * @function + * @param {RequestInfo} url + * @param {RequestInit} options + * @returns {Promise} + */ +export const fetchText = async (url, options = {}) => + await (await fetch(url, options)).text(); + +/** + * Load an item and parse the Response as json + * @function + * @param {RequestInfo} url + * @param {RequestInit} options + * @returns {Promise} + */ +export const fetchJson = async (url, options = {}) => + await (await fetch(url, options)).json(); + +/** + * Load an item and parse the Response as arrayBuffer + * @function + * @param {RequestInfo} url + * @param {RequestInit} options + * @returns {Promise} + */ +export const fetchArrayBuffer = async (url, options = {}) => + await (await fetch(url, options)).arrayBuffer(); + +/** + * Load an item and parse the Response as blob + * @function + * @param {RequestInfo} url + * @param {RequestInit} options + * @returns {Promise} + */ +export const fetchBlob = async (url, options = {}) => + await (await fetch(url, options)).blob(); + +/** + * Load an item, parse the Response as blob and create a HTML Image + * @function + * @param {string | ImageOptions} urlOrOpts + * @param {RequestInit} options + * @returns {Promise} + */ +export const fetchImage = async (urlOrOpts, options = {}) => { + const img = new Image(); + + let src = urlOrOpts; + if (urlOrOpts.url) { + const { url, ...rest } = urlOrOpts; + src = url; + try { + Object.assign(img, rest); + } catch (error) { + return Promise.reject(new Error(error)); + } + } + + const data = await fetchBlob(src, options); + + return await new Promise((resolve, reject) => { + img.addEventListener("load", function load() { + img.removeEventListener("load", load); + resolve(img); + }); + img.addEventListener("error", function error() { + img.removeEventListener("error", error); + reject(img); + }); + + img.src = URL.createObjectURL(data); + }); +}; + +const LOADERS_MAP = { + text: fetchText, + json: fetchJson, + image: fetchImage, + blob: fetchBlob, + binary: fetchArrayBuffer, +}; +const LOADERS_MAP_KEYS = Object.keys(LOADERS_MAP); + +/** + * Loads resources from a named map + * @function + * @param {Object.} resources + * @returns {Promise>} + * + * @example + * const resources = { + * hello: { text: "assets/hello.txt" }, + * data: { json: "assets/data.json" }, + * img: { image: "assets/tex.jpg" }, + * hdrImg: { binary: "assets/tex.hdr" }, + * blob: { binary: "assets/blob" }, + * }; + * + * const res = await io.fetchAll(resources); + * res.hello; // => DOMString + * res.data; // => Object + * res.img; // => HTMLImageElement + * res.hdrImg; // => ArrayBuffer + * res.blob; // => Blob + */ +export const fetchAll = (resources) => { + const names = Object.keys(resources); + + return Promise.allSettled( + names.map(async (name) => { + const res = resources[name]; + const loader = LOADERS_MAP_KEYS.find((loader) => res[loader]); + if (loader) return await LOADERS_MAP[loader](res[loader]); + return Promise.reject( + new Error(`io.load: unknown resource type "${Object.keys(res)}". +Resource needs one of ${LOADERS_MAP_KEYS.join("|")} set to an url.`) + ); + }) + ).then((values) => + Object.fromEntries( + Array.from( + values.map((v) => v.value || v.reason), + (v, i) => [names[i], v] + ) + ) + ); +}; diff --git a/index.html b/index.html index 399fcb0..9575c3e 100644 --- a/index.html +++ b/index.html @@ -48,6 +48,7 @@

pex-io

json: "assets/color.json", image: "assets/pex.png", binary: "assets/data.bin", + blob: "assets/hello.txt", errorNotFound: "assets/not-found.ext", }; @@ -58,9 +59,12 @@

pex-io

"callback-batch": { ...assetState }, async: { ...assetState }, "async-batch": { ...assetState }, + fetch: { ...assetState, blob: null }, + "fetch-batch": { ...assetState, blob: null }, error: { ...assetState, error: null }, "image-options": { all: null, readOnly: null, urlOnly: null }, }; + window.state = state; const app = () => () => { return [ @@ -176,6 +180,63 @@

pex-io

state["async-batch"].binary = res.data; })(); + // fetch + (async () => { + try { + state.fetch.text = await io.fetchText(ASSETS.text); + } catch (error) { + state.fetch.text = error; + console.log("fetch", error); + } + try { + state.fetch.json = await io.fetchJson(ASSETS.json); + } catch (error) { + state.fetch.json = error; + console.log("fetch", error); + } + try { + state.fetch.image = await io.fetchImage(ASSETS.image); + } catch (error) { + state.fetch.image = error; + console.log("fetch", error); + } + try { + state.fetch.binary = await io.fetchArrayBuffer(ASSETS.binary); + } catch (error) { + state.fetch.binary = error; + console.log("fetch", error); + } + try { + state.fetch.blob = await io.fetchBlob(ASSETS.blob); + state.fetch.blob = await state.fetch.blob.text(); + } catch (error) { + state.fetch.blob = error; + console.log("fetch", error); + } + })(); + + // fetch-batch + (async () => { + let res; + try { + res = await io.fetchAll({ + hello: { text: ASSETS.text }, + color: { json: ASSETS.json }, + pex: { image: ASSETS.image }, + data: { binary: ASSETS.binary }, + blob: { blob: ASSETS.blob }, + }); + } catch (err) { + res = err; + console.log("fetch batch", filterResultsErrors(err)); + } + state["fetch-batch"].text = res.hello; + state["fetch-batch"].json = res.color; + state["fetch-batch"].image = res.pex; + state["fetch-batch"].binary = res.data; + state["fetch-batch"].blob = await res.blob.text(); + })(); + // Error (() => { io.loadText(ASSETS.errorNotFound, (err, text) => { diff --git a/index.js b/index.js index ca290d6..ac37ad8 100644 --- a/index.js +++ b/index.js @@ -3,3 +3,4 @@ export { default as loadText } from "./loadText.js"; export { default as loadJSON } from "./loadJSON.js"; export { default as loadImage } from "./loadImage.js"; export { default as loadBinary } from "./loadBinary.js"; +export * from "./fetch.js"; diff --git a/load.js b/load.js index 90dc1ee..73270df 100644 --- a/load.js +++ b/load.js @@ -60,14 +60,11 @@ function load(resources, callback) { Promise.allSettled( names.map(async (name) => { const res = resources[name]; - const loader = LOADERS_MAP_KEYS.find((loader) => res[loader]); if (loader) return await LOADERS_MAP[loader](res[loader]); return Promise.reject( - new Error( - `io.load: unknown resource type "${Object.keys(res)}". -Resource needs one of ${LOADERS_MAP_KEYS.join("|")} set to an url.` - ) + new Error(`io.load: unknown resource type "${Object.keys(res)}". +Resource needs one of ${LOADERS_MAP_KEYS.join("|")} set to an url.`) ); }) ).then((values) => {