Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trackedTask returns last task value if current task value is null or undefined #793

Closed
sergey-zhidkov opened this issue Mar 6, 2023 · 5 comments

Comments

@sergey-zhidkov
Copy link
Contributor

sergey-zhidkov commented Mar 6, 2023

In case if task was called several times and the last returned value was null or undefined, then trackedTask returns last (previous) value instead of the correct current one.

For example:

import Component from '@glimmer/component';
import { keepLatestTask } from 'ember-concurrency';
import { trackedTask } from 'ember-resources/util/ember-concurrency';
import { taskFor } from 'ember-concurrency-ts';

export default class ChildComponent extends Component {
  resultTask = trackedTask(this, taskFor(this.myTask), () => [
    this.args.myArg,
  ]);

  get value() {
    return this.resultTask.value;
  }

  getResultFromArg(myArg) {
    if (myArg === 0) {
      return 'non null non undefined result';
    } else {
      // This value will be lost if it was returned as the latest result of task run
      return undefined;

      // This value will be lost as well
      // return null;

      // This one will be returned from "trackedTask" as expected
      // return 'result';
    }
  }

  @keepLatestTask
  *myTask(myArg) {
    const result = yield this.getResultFromArg(myArg);
    console.log('result in context of ', myArg, '>>', result);
    return result;
  }
}

Template

<div>
  <div>value</div>
  <div>
    <strong>{{this.value}}</strong>
  </div>
</div>

Steps to reproduce:
step 1: we pass "0" as value of "myArg" to Child Component => myTask will return "non null non undefined result" value. It will set this.currentTask value to non null non undefined result at https://github.com/NullVoxPopuli/ember-resources/blob/main/ember-resources/src/util/ember-concurrency.ts#L225.
step 2: we pass "1" as value of "myArg" to Child Component => myTask will return undefined value. It will set this.currentTask value to undefined.
step 3: test that getter returns non null non undefined result instead of expected undefined.

get value() {
    return this.resultTask.value; // will return `non null non undefined result`
}

I believe this is happening because of the code in TaskResource class https://github.com/NullVoxPopuli/ember-resources/blob/main/ember-resources/src/util/ember-concurrency.ts#L217

  get value() {
    return this.currentTask.value ?? this.lastTask?.value;
  }

I wonder if this is expected behavior.

@NullVoxPopuli
Copy link
Owner

Is this with v5 or the v6beta?

@NullVoxPopuli
Copy link
Owner

I wonder if this is expected behavior

It is not, and i think you investigated the bug beautifully!

The value getter probably needs to consider if current task is finished before deciding to return lastTask.value or currentTask.value, rather than the existing naiive ??

Excellent find!

@NullVoxPopuli
Copy link
Owner

@sergey-zhidkov would you be willing to submit a PR?

maybe something to the effect of:

  get value() {
    if (this.return.currentTask?.isFinished) return this.currentTask?.value;
    
    return this.lastTask?.value;
  }

?

@sergey-zhidkov
Copy link
Contributor Author

It's v5.

Excellent find!

Thank you.

The value getter probably needs to consider if current task is finished before deciding to return lastTask.value or currentTask.value, rather than the existing naiive ??

I do agree. This is a good way to fix the issue.

@sergey-zhidkov would you be willing to submit a PR?

I'll be happy to. I'll try to do it by the end of Wednesday. Probably will take some time to write proper tests.

@sergey-zhidkov
Copy link
Contributor Author

Fix was merged to main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants