Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Calling resource.set(value) does not abort in-progress loaders if the given value is equal to the value before the resource was reloaded #59272

Copy link
Copy link
@daiscog

Description

@daiscog
Issue body actions

Which @angular/* package(s) are the source of the bug?

core

Is this a regression?

No

Description

I'm not sure whether this is a bug or whether this is intended, but it feels unintuitive to me. Therefore "expected" below is what I would have expected.

Expected behaviour

Calling resouce.set(value) should always abort in-progress async loading

Actual behaviour

Calling resouce.reload() then calling resouce.set(value) before the async reload is complete, with the same value that was set for the resource before reload was called, does not abort the reload operation.

This creates an inconsistent behaviour. E.g.:

resource.set({});
resources.reload();
resource.set(undefined); // cancels the reload


resource.set(undefined);
resources.reload();
resource.set(undefined); // does not cancel the reload

Example reproduction

In the following component, click the "Load it" button to trigger the reload, then click the "Cancel it" button to set the resource explicitly to undefined before the async load operation has completed.

import {Component, resource, ResourceStatus} from '@angular/core';
import {JsonPipe} from '@angular/common';

@Component({
  selector: 'app-root',
  imports: [JsonPipe],
  template: `
    <p>
      @if (something.value()) {
        {{something.value() | json}}
      } @else if (something.isLoading()) {
        Loading...
      } @else {
        Load it?
      }
    </p>
    @if (something.isLoading()) {
      <p><button type="button" (click)="cancelIt()">Cancel it</button></p>
    } @else {
      <p><button type="button" (click)="loadIt()">Load it</button></p>
    }
  `
})
export class AppComponent {
  readonly something = resource({
    loader: async ({previous, abortSignal}) => {
      if (previous.status === ResourceStatus.Idle) {
        return undefined;
      }
      return await someLongRunningTask(abortSignal);
    }
  });

  loadIt() {
    this.something.reload();
  }

  cancelIt() {
    // Setting a value after reload is called that is the same as the value
    // which was set before reload was called does not cancel the reload action
    this.something.set(undefined);

    // whereas setting a different value to the previous one always aborts in-progress reload operations
    // this.something.set({});
  }
}

function someLongRunningTask(abortSignal: AbortSignal) {
  return new Promise<unknown>((resolve, reject) => {
    if (abortSignal.aborted) {
      reject(abortSignal.reason);
      return;
    }

    let timeout: number | undefined = undefined;
    const abort = () => {
      clearTimeout(timeout);
      reject(abortSignal.reason);
    };
    abortSignal.addEventListener('abort', abort);
    timeout = setTimeout(() => {
      abortSignal.removeEventListener('abort', abort);
      resolve({success: true});
    }, 2_000)
  })
}

Please provide a link to a minimal reproduction of the bug

No response

Please provide the exception or error you saw


Please provide the environment you discovered this bug in (run ng version)

Angular CLI: 19.0.6
Node: 20.18.1
Package Manager: npm 10.8.2
OS: darwin arm64

Angular: 19.0.5
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1900.6
@angular-devkit/build-angular   19.0.6
@angular-devkit/core            19.0.6
@angular-devkit/schematics      19.0.6
@angular/cli                    19.0.6
@schematics/angular             19.0.6
rxjs                            7.8.1
typescript                      5.6.3
zone.js                         0.15.0

Anything else?

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions

    Morty Proxy This is a proxified and sanitized view of the page, visit original site.