Allows wrapper functions to provide a resource for use in templates.
Only library authors may care about this, but helper function is needed to "register" the wrapper function with a helper manager that specifically handles invoking both the resource wrapper function as well as the underlying resource.
App-devs / consumers may not ever need to know this utility function exists
Example using strict mode + syntax and a template-only component:
import { resource, registerResourceWrapper } from 'ember-resources/util/function-resource';
function RemoteData(url) {
return resource(({ on }) => {
let state = new TrackedObject({});
let controller = new AbortController();
on.cleanup(() => controller.abort());
fetch(url, { signal: controller.signal })
.then(response => response.json())
.then(data => {
state.value = data;
})
.catch(error => {
state.error = error;
});
return state;
})
}
registerResourceWrapper(RemoteData)
<template>
{{#let (load) as |state|}}
{{#if state.value}}
...
{{else if state.error}}
{{state.error}}
{{/if}}
{{/let}}
</template>
Alternatively, registerResourceWrapper can wrap the wrapper function.
const RemoteData = registerResourceWrapper((url) => {
return resource(({ on }) => {
...
});
})
resource is an alternative API to the class-based Resource.
It provides a single read-only value and provides a way to optionally cleanup.
When would you reach for the class-based Resource?
A function-resource
Example using fetch + AbortController
import { use, resource } from 'ember-resources/util/function-resource';
import { TrackedObject } from 'tracked-built-ins';
import { tracked } from '@glimmer/tracking';
class Demo {
@tracked url = '...';
@use myData = resource(({ on }) => {
let state = new TrackedObject({ ... });
let controller = new AbortController();
on.cleanup(() => controller.abort());
// because this.url is tracked, anytime url changes,
// this resource will re-run
fetch(this.url, { signal: controller.signal })
.then(response => response.json())
.then(data => {
state.value = data;
// ...
})
.catch(error => {
state.error = error;
// ...
});
// Note that this fetch request could be written async by wrapping in an
// immediately invoked async function, e.g: (async () => {})()
return state;
})
}
resource is an alternative API to the class-based Resource.
It provides a single read-only value and provides a way to optionally cleanup.
When would you reach for the class-based Resource?
A function-resource
Example using fetch + AbortController
import { resource } from 'ember-resources/util/function-resource';
import { TrackedObject } from 'tracked-built-ins';
import { tracked } from '@glimmer/tracking';
class Demo {
@tracked url = '...';
myData = resource(this, ({ on }) => {
let state = new TrackedObject({ isResolved: false, isLoading: true, isError: false });
let controller = new AbortController();
on.cleanup(() => controller.abort());
// because this.url is tracked, anytime url changes,
// this resource will re-run
fetch(this.url, { signal: controller.signal })
.then(response => response.json())
.then(data => {
state.value = data;
state.isResolved = true;
state.isLoading = false;
state.isError = false;
})
.catch(error => {
state.error = error;
state.isResolved = true;
state.isLoading = false;
state.isError = true;
});
// Note that this fetch request could be written async by wrapping in an
// immediately invoked async function, e.g: (async () => {})()
return state;
})
}
The @use decorator has two responsibilities
This @use decorator is needed for function-resources, and not needed for class-based
resources (for now).
Generated using TypeDoc
Optionally a function-resource can provide a cleanup function.
Example: