NullVoxPopuli / ember-resources

An implementation of Resources. Supports ember 3.28+
https://github.com/NullVoxPopuli/ember-resources/blob/main/docs/docs/README.md
MIT License
90 stars 37 forks source link

usetask call twice on component setup #194

Closed oliverlj closed 3 years ago

oliverlj commented 3 years ago

component

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';

import { task } from 'ember-concurrency';
import { taskFor } from 'ember-concurrency-ts';
import { useTask } from 'ember-resources';

import type { BsForm } from 'ember-bootstrap';
import type { TaskInstance, TaskIsh } from 'ember-resources/-private/resources/ember-concurrency-task';
import type CoinGeckoCoin from 'fz-front-simulator/objects/cgc/coin-gecko-coin';
import type CryptoService from 'fz-front-simulator/services/crypto-service';

interface CryptoFormCurrencySelectorArgs {
  assetId?: string;
  form: BsForm;
  onChange: (asset: CoinGeckoCoin) => void;
}

export default class CryptoFormCurrencySelector extends Component<CryptoFormCurrencySelectorArgs> {
  @service declare cryptoService: CryptoService;

  @tracked asset?: CoinGeckoCoin;
  @tracked cryptoCurrencyFilter = '';
  @tracked task!: TaskInstance<unknown>;

  constructor(owner: never, args: CryptoFormCurrencySelectorArgs) {
    super(owner, args);
    this.fetchCryptos();
  }

  @action
  fetchCryptos() {
    this.task = useTask(this, this.testTask as unknown as TaskIsh);
  }

  get cryptoCurrencies(): CoinGeckoCoin[] {
    return this.cryptoService.getCryptosByCode(this.cryptoCurrencyFilter);
  }

  @action
  setAsset(value: CoinGeckoCoin) {
    this.asset = value;
    this.args.onChange(value);
  }

  @action
  setCryptoCurrencyFilter(value: string) {
    this.cryptoCurrencyFilter = value;
  }

  @task
  async testTask() {
    await taskFor(this.cryptoService.fetchCryptosTask).perform();

    if (this.args.assetId) {
      const asset = this.cryptoService.getCrypto(this.args.assetId);

      if (asset) {
        this.setAsset(asset);
      }
    }
  }
}
<@form.element
  @controlType="power-select"
  @onChange={{this.setAsset}}
  @options={{this.cryptoCurrencies}}
  @value={{this.asset}}
  @label={{t "components.crypto.form.currency-selector.label"}}
  as |el|
>
  {{#if this.task.isRunning}}
    <ContentLoader::FormControl />
  {{else if this.task.isSuccessful}}
    <el.control
      @noMatchesMessage={{t "components.crypto.form.currency-selector.no-results"}}
      @placeholder={{t "components.crypto.form.currency-selector.placeholder"}}
      @search={{this.setCryptoCurrencyFilter}}
      @searchEnabled={{true}}
      @searchMessage={{t "components.crypto.form.currency-selector.search"}}
      as |cryptoCurrency|
    >
      {{cryptoCurrency.name}}
      ({{cryptoCurrency.symbol}})
    </el.control>
  {{else if this.task.isError}}
    <BsButton @onClick={{this.fetchCryptos}} @outline={{true}} @type="danger" class="form-control is-invalid">{{t
        "components.crypto.form.currency-selector.retry"
      }}</BsButton>
    <div class="invalid-feedback">{{t "components.crypto.form.currency-selector.invalid-feedback"}}</div>
  {{/if}}

</@form.element>

First stacktrace call

testTask (currency-selector.js:94)
step (generator-state.js:33)
generatorStep (executor.js:279)
handleResolvedContinueValue (executor.js:143)
proceedSync (executor.js:106)
start (executor.js:46)
start (base.js:73)
(anonymous) (refresh.js:25)
process (refresh.js:25)
refresh (scheduler.js:48)
perform (scheduler.js:39)
_performShared (task.js:123)
_perform (task.js:105)
update (ember-concurrency-task.js:33)
setup (ember-concurrency-task.js:25)
setupInstance (lifecycle.js:62)
(anonymous) (lifecycle.js:36)
getValue (validator.js:771)
getValue (lifecycle.js:47)
(anonymous) (runtime.js:6777)
getValue (validator.js:771)
get value (ember-concurrency.js:48)
get (ember-concurrency.js:57)
getPossibleMandatoryProxyValue (index.js:1322)
_getProp (index.js:1390)
(anonymous) (reference.js:213)
(anonymous) (reference.js:161)
track (validator.js:820)
valueForRef (reference.js:160)
(anonymous) (runtime.js:2500)
(anonymous) (reference.js:161)
track (validator.js:820)
valueForRef (reference.js:160)
(anonymous) (runtime.js:2458)
evaluate (runtime.js:1284)
evaluateSyscall (runtime.js:5117)
evaluateInner (runtime.js:5073)
evaluateOuter (runtime.js:5065)
next (runtime.js:6034)
_execute (runtime.js:6018)
execute (runtime.js:5988)
(anonymous) (runtime.js:6091)
runInTrackingTransaction (validator.js:154)
sync (runtime.js:6091)
(anonymous) (index.js:7483)
(anonymous) (index.js:7452)
(anonymous) (index.js:7799)
inTransaction (runtime.js:4959)
_renderRoots (index.js:7779)
_renderRootsTransaction (index.js:7831)
_renderRoot (index.js:7766)
_appendDefinition (index.js:7673)
appendOutletView (index.js:7655)
invoke (backburner.js:340)
flush (backburner.js:229)
flush (backburner.js:426)
_end (backburner.js:958)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_ensureInstance (backburner.js:1165)
ensureInstance (backburner.js:920)
scheduleRevalidate (index.js:5946)
dirtyTag (validator.js:475)
dirtyTagFor (validator.js:578)
markObjectAsDirty (index.js:545)
notifyPropertyChange (index.js:583)
_setProp (index.js:1579)
set (index.js:1545)
set (intl.js:31)
_set (index.js:2054)
set (index.js:1994)
CPSETTER_FUNCTION (index.js:1038)
_setProp (index.js:1552)
set (index.js:1545)
setLocale (intl.js:201)
loadTranslations (intl-config.js:40)
await in loadTranslations (async)
beforeModel (route.js:29)
runBeforeModelHook (router_js.js:807)
(anonymous) (router_js.js:713)
tryCatcher (rsvp.es.js:170)
invokeCallback (rsvp.es.js:170)
publish (rsvp.es.js:170)
(anonymous) (rsvp.js:19)
invoke (backburner.js:338)
flush (backburner.js:229)
flush (backburner.js:426)
_end (backburner.js:958)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_ensureInstance (backburner.js:1165)
schedule (backburner.js:774)
(anonymous) (rsvp.js:19)
fulfill (rsvp.es.js:170)
resolve$1 (rsvp.es.js:170)
eval (rsvp.es.js:170)
Promise.then (async)
tryCatcher (rsvp.es.js:170)
eval (rsvp.es.js:170)
(anonymous) (rsvp.js:19)
invoke (backburner.js:338)
flush (backburner.js:229)
flush (backburner.js:426)
_end (backburner.js:958)
end (backburner.js:708)
_run (backburner.js:1013)
run (backburner.js:752)
run (index.js:116)
callback (application.js:434)

Second strak trace call

testTask (currency-selector.js:94)
step (generator-state.js:33)
generatorStep (executor.js:279)
handleResolvedContinueValue (executor.js:143)
proceedSync (executor.js:106)
start (executor.js:46)
start (base.js:73)
(anonymous) (refresh.js:25)
process (refresh.js:25)
refresh (scheduler.js:48)
perform (scheduler.js:39)
_performShared (task.js:123)
_perform (task.js:105)
update (ember-concurrency-task.js:33)
(anonymous) (lifecycle.js:38)
getValue (validator.js:771)
getValue (lifecycle.js:47)
(anonymous) (runtime.js:6777)
getValue (validator.js:771)
get value (ember-concurrency.js:48)
get (ember-concurrency.js:57)
getPossibleMandatoryProxyValue (index.js:1322)
_getProp (index.js:1390)
(anonymous) (reference.js:213)
(anonymous) (reference.js:161)
track (validator.js:820)
valueForRef (reference.js:160)
(anonymous) (runtime.js:2500)
(anonymous) (reference.js:161)
track (validator.js:820)
valueForRef (reference.js:160)
evaluate (runtime.js:2514)
_execute (runtime.js:5169)
(anonymous) (runtime.js:5139)
runInTrackingTransaction (validator.js:154)
execute (runtime.js:5139)
rerender (runtime.js:5517)
(anonymous) (index.js:7485)
(anonymous) (index.js:7452)
(anonymous) (index.js:7799)
inTransaction (runtime.js:4959)
_renderRoots (index.js:7779)
_renderRootsTransaction (index.js:7831)
_revalidate (index.js:7873)
invoke (backburner.js:338)
flush (backburner.js:229)
flush (backburner.js:426)
_end (backburner.js:958)
end (backburner.js:708)
_run (backburner.js:1013)
_join (backburner.js:987)
join (backburner.js:758)
join (index.js:165)
async (ember-environment.js:15)
proceedAsync (executor.js:93)
proceedChecked (executor.js:83)
(anonymous) (executor.js:186)
Promise.then (async)
handleYieldedUnknownThenable (executor.js:185)
handleYieldedValue (executor.js:232)
handleResolvedContinueValue (executor.js:154)
proceedSync (executor.js:106)
(anonymous) (executor.js:93)
invoke (backburner.js:338)
flush (backburner.js:229)
flush (backburner.js:426)
_end (backburner.js:958)
end (backburner.js:708)
_run (backburner.js:1013)
_join (backburner.js:987)
join (backburner.js:758)
join (index.js:165)
async (ember-environment.js:15)
proceedAsync (executor.js:93)
proceedChecked (executor.js:83)
(anonymous) (executor.js:186)
Promise.then (async)
handleYieldedUnknownThenable (executor.js:185)
handleYieldedValue (executor.js:232)
handleResolvedContinueValue (executor.js:154)
proceedSync (executor.js:106)
start (executor.js:46)
start (base.js:73)
(anonymous) (refresh.js:25)
process (refresh.js:25)
refresh (scheduler.js:48)
perform (scheduler.js:39)
_performShared (task.js:123)
_perform (task.js:105)
testTask (currency-selector.js:94)
step (generator-state.js:33)
generatorStep (executor.js:279)
handleResolvedContinueValue (executor.js:143)
proceedSync (executor.js:106)
start (executor.js:46)
start (base.js:73)
(anonymous) (refresh.js:25)
process (refresh.js:25)
refresh (scheduler.js:48)
perform (scheduler.js:39)
_performShared (task.js:123)
_perform (task.js:105)
update (ember-concurrency-task.js:33)
setup (ember-concurrency-task.js:25)
setupInstance (lifecycle.js:62)
(anonymous) (lifecycle.js:36)
getValue (validator.js:771)
getValue (lifecycle.js:47)
(anonymous) (runtime.js:6777)
getValue (validator.js:771)
get value (ember-concurrency.js:48)
get (ember-concurrency.js:57)
getPossibleMandatoryProxyValue (index.js:1322)
_getProp (index.js:1390)
(anonymous) (reference.js:213)
(anonymous) (reference.js:161)
track (validator.js:820)
valueForRef (reference.js:160)
(anonymous) (runtime.js:2500)
(anonymous) (reference.js:161)
track (validator.js:820)
valueForRef (reference.js:160)
(anonymous) (runtime.js:2458)
evaluate (runtime.js:1284)
evaluateSyscall (runtime.js:5117)
evaluateInner (runtime.js:5073)
evaluateOuter (runtime.js:5065)
next (runtime.js:6034)
_execute (runtime.js:6018)
execute (runtime.js:5988)
(anonymous) (runtime.js:6091)
runInTrackingTransaction (validator.js:154)
sync (runtime.js:6091)
(anonymous) (index.js:7483)
(anonymous) (index.js:7452)
(anonymous) (index.js:7799)
inTransaction (runtime.js:4959)
_renderRoots (index.js:7779)
_renderRootsTransaction (index.js:7831)
_renderRoot (index.js:7766)
_appendDefinition (index.js:7673)
appendOutletView (index.js:7655)
invoke (backburner.js:340)
flush (backburner.js:229)
flush (backburner.js:426)
_end (backburner.js:958)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_end (backburner.js:968)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_ensureInstance (backburner.js:1165)
ensureInstance (backburner.js:920)
scheduleRevalidate (index.js:5946)
dirtyTag (validator.js:475)
dirtyTagFor (validator.js:578)
markObjectAsDirty (index.js:545)
notifyPropertyChange (index.js:583)
_setProp (index.js:1579)
set (index.js:1545)
set (intl.js:31)
_set (index.js:2054)
set (index.js:1994)
CPSETTER_FUNCTION (index.js:1038)
_setProp (index.js:1552)
set (index.js:1545)
setLocale (intl.js:201)
loadTranslations (intl-config.js:40)
await in loadTranslations (async)
beforeModel (route.js:29)
runBeforeModelHook (router_js.js:807)
(anonymous) (router_js.js:713)
tryCatcher (rsvp.es.js:170)
invokeCallback (rsvp.es.js:170)
publish (rsvp.es.js:170)
(anonymous) (rsvp.js:19)
invoke (backburner.js:338)
flush (backburner.js:229)
flush (backburner.js:426)
_end (backburner.js:958)
Backburner._boundAutorunEnd (backburner.js:627)
Promise.then (async)
iterations (backburner.js:28)
flush (index.js:43)
_scheduleAutorun (backburner.js:1177)
_ensureInstance (backburner.js:1165)
schedule (backburner.js:774)
(anonymous) (rsvp.js:19)
fulfill (rsvp.es.js:170)
resolve$1 (rsvp.es.js:170)
eval (rsvp.es.js:170)
Promise.then (async)
tryCatcher (rsvp.es.js:170)
eval (rsvp.es.js:170)
(anonymous) (rsvp.js:19)
invoke (backburner.js:338)
flush (backburner.js:229)
flush (backburner.js:426)
_end (backburner.js:958)
end (backburner.js:708)
_run (backburner.js:1013)
run (backburner.js:752)
run (index.js:116)
callback (application.js:434)
NullVoxPopuli commented 3 years ago

Change

@action
  fetchCryptos() {
    this.task = useTask(this, this.testTask as unknown as TaskIsh);
  }

To

    task = useTask(this, this.testTask as unknown as TaskIsh);

useTask and all the resources work best as whole properties, rather that created and invoked manually.

They invoke themselves automatically upon access.