In our project we have a following class based resource
export class MinuteTimer extends Resource<MinuteTimerArgs> {
@service
declare dateManager: DateManagerService;
@tracked localDateTime: LocalDateTime | undefined;
valueSet = false;
constructor(...args: ConstructorParameters<typeof Resource>) {
super(...args);
registerDestructor(this, () => {
// final teardown
this.tickLocalMinute.cancelAll();
});
}
tickLocalMinute = dropTask(
async (condition = () => true, testEnvironmentTimeoutMs: number) => {
// this helps during the testing to update the localDateTime this number of times and then breaking
let testCountdown = 3;
do {
const now = this.dateManager.getCurrentLocalDateTimeAtVenue();
// update the localDateTime when a condition is true
// but set it unconditionally for the 1st time
if (!this.valueSet || condition(now)) {
this.localDateTime = now;
this.valueSet = true;
}
const startOfTheNextMinute = now
.plusMinutes(1)
.truncatedTo(ChronoUnit.MINUTES);
if (config.APP['isNotTestEnvironment']) {
await timeout(
this.dateManager.differenceInMilliseconds(
now,
startOfTheNextMinute,
) + 50, // This buffer of 50ms is just to be on the safe side
); // adaptive timer that will continue when the next minute starts
} else {
await timeout(testEnvironmentTimeoutMs);
}
} while (config.APP['isNotTestEnvironment'] || --testCountdown);
},
);
modify(
_positional: Positional<MinuteTimerArgs>,
{
condition = () => true,
testEnvironmentTimeoutMs,
}: Named<MinuteTimerArgs>,
) {
this.tickLocalMinute.perform(condition, testEnvironmentTimeoutMs);
}
}
basically it's a timer which has a few additions: it updates the tracked value when a condition is met (optionally) and also we can tell it to break the cycle after a few attempts. This logic was implemented using an ember-concurrency task. A few days ago i found out that class-based resources are discouraged in the favor of function-based resources. I try to rewrite this resource like this
export function MinuteTimer(
condition: (d: LocalDateTime | undefined) => boolean = () => true,
testEnvironmentTimeoutMs: number = 100,
) {
return resource(({ owner, on }) => {
const dateManager = owner.lookup('service:date-manager');
const localDateTime = cell<LocalDateTime>();
let valueSet = false;
const tickLocalMinute = task(
async (
condition: (d: LocalDateTime | undefined) => boolean = () => true,
testEnvironmentTimeoutMs: number,
) => {
// this helps during the testing to update the localDateTime this number of times and then breaking
let testCountdown = 3;
do {
const now = dateManager.getCurrentLocalDateTimeAtVenue();
// update the localDateTime when a condition is true
// but set it unconditionally for the 1st time
if (!valueSet || condition(now)) {
localDateTime.current = now;
valueSet = true;
}
const startOfTheNextMinute = now
.plusMinutes(1)
.truncatedTo(ChronoUnit.MINUTES);
if (config.APP['isNotTestEnvironment']) {
await timeout(
dateManager.differenceInMilliseconds(now, startOfTheNextMinute) +
50, // This buffer of 50ms is just to be on the safe side
); // adaptive timer that will continue when the next minute starts
} else {
await timeout(testEnvironmentTimeoutMs);
}
} while (config.APP['isNotTestEnvironment'] || --testCountdown);
},
);
on.cleanup(() => {
// final teardown
tickLocalMinute.cancelAll();
});
// debugger;
tickLocalMinute.perform(condition, testEnvironmentTimeoutMs);
return () => {
return localDateTime.current;
};
});
}
resourceFactory(MinuteTimer);
but i receive the following error:
So basically it tells me that i can't declare tasks in functions (which i guess is the case). I've got a few questions:
- Is my understanding correct: do i receive an error because i declare a task in the function?
- Is my other idea correct: we'd better should convert class-based resources into function-based resources?
- Can i do that anyhow and still keep an ember-concurrency task? I guess i'd be able to rewrite this particular one using plain js functions but I am asking mainly because we have a couple more resources where we use tasks to wrap network calls like data fetching when a tracked value changes.
- Does out approach make sense or do we completely misunderstand the concept of both tasks and resources?
