admin管理员组文章数量:1278880
I have been defining resource as follows:
resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
request: (): ResourceRequest | undefined => {
return {
id: this.id(),
};
},
loader: ({ request: { id }, abortSignal }) => {
return fetch(`/${id}`).then(
(res: any) => res.json()
);
},
});
Seems sufficient to achieve what I want, but I see this pattern in blogs and youtube where they add the AbortSignal
to the fetch request.
loader: ({ request: { id }, abortSignal }) => {
return fetch(`/${id}`, {
signal: abortSignal,
}).then((res: any) => res.json());
},
What is the necessity for this?
Below is my minimal reproducible code with working stackblitz.
TS:
id = signal(1);
rs = ResourceStatus;
http = inject(HttpClient);
resourceControl = signal(true);
resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
request: (): ResourceRequest | undefined => {
return {
id: this.id(),
};
},
loader: ({ request: { id }, abortSignal }) => {
return fetch(`/${id}`).then(
(res: any) => res.json()
);
},
});
HTML:
<div>
<div>
Resource Request triggers:
</div>
<div>
<input [(ngModel)]="id" type="number"/>
</div>
</div>
<div>
@if(![rs.Loading, rs.Reloading].includes(resource.status())) {
{{resource.value() | json}}
} @else{
Loading...
}
</div>
Stackblitz Demo
I have been defining resource as follows:
resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
request: (): ResourceRequest | undefined => {
return {
id: this.id(),
};
},
loader: ({ request: { id }, abortSignal }) => {
return fetch(`https://jsonplaceholder.typicode/todos/${id}`).then(
(res: any) => res.json()
);
},
});
Seems sufficient to achieve what I want, but I see this pattern in blogs and youtube where they add the AbortSignal
to the fetch request.
loader: ({ request: { id }, abortSignal }) => {
return fetch(`https://jsonplaceholder.typicode/todos/${id}`, {
signal: abortSignal,
}).then((res: any) => res.json());
},
What is the necessity for this?
Below is my minimal reproducible code with working stackblitz.
TS:
id = signal(1);
rs = ResourceStatus;
http = inject(HttpClient);
resourceControl = signal(true);
resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
request: (): ResourceRequest | undefined => {
return {
id: this.id(),
};
},
loader: ({ request: { id }, abortSignal }) => {
return fetch(`https://jsonplaceholder.typicode/todos/${id}`).then(
(res: any) => res.json()
);
},
});
HTML:
<div>
<div>
Resource Request triggers:
</div>
<div>
<input [(ngModel)]="id" type="number"/>
</div>
</div>
<div>
@if(![rs.Loading, rs.Reloading].includes(resource.status())) {
{{resource.value() | json}}
} @else{
Loading...
}
</div>
Stackblitz Demo
Share Improve this question edited Feb 24 at 10:16 Naren Murali asked Feb 24 at 4:03 Naren MuraliNaren Murali 58.2k5 gold badges44 silver badges76 bronze badges1 Answer
Reset to default 2From the documentation:
resource
will cancel in-progress loads via theAbortSignal
when destroyed or when a new request object becomes available, which could prematurely abort mutations.
The syntax to configure the AbortController
is as follows:
resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
...
loader: ({ request: { id }, abortSignal }) => {
return fetch(`https://jsonplaceholder.typicode/todos/${id}`, {
signal: abortSignal
}).then((res: any) => res.json();
},
});
The signal
property from RequestInit Object - MDN Docs
An
AbortSignal
. If this option is set, the request can be canceled by callingabort()
on the corresponding AbortController.
So providing the AbortController
will do two things:
When a new request object arrives the previous still running requests are aborted (cancelled) - thus saving network resources.
When the resource is itself destroyed the still running requests are aborted.
In the below screenshots you can see the difference between using it and not using it:
Without Abort Controller:
With Abort Controller:
For rxResource
this is not a prerequisite, since it automatically performs this action, similar to the switchMap
behavior of rxjs (does not use switchMap though).
Full Code:
import {
Component,
inject,
ResourceRef,
ResourceStatus,
signal,
resource,
} from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { rxResource } from '@angular/core/rxjs-interop';
import { HttpClient, provideHttpClient } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
export interface ResourceRequest {
id: number;
}
@Component({
selector: 'app-root',
imports: [CommonModule, FormsModule],
template: `
<div>
<div>
Resource Request triggers:
</div>
<div>
<input [(ngModel)]="id" type="number"/>
</div>
</div>
<div>
@if(![rs.Loading, rs.Reloading].includes(resource.status())) {
{{resource.value() | json}}
} @else{
Loading...
}
</div>
`,
})
export class App {
id = signal(1);
rs = ResourceStatus;
http = inject(HttpClient);
resourceControl = signal(true);
resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
request: (): ResourceRequest | undefined => {
return {
id: this.id(),
};
},
loader: ({ request: { id }, abortSignal }) => {
return fetch(`https://jsonplaceholder.typicode/todos/${id}`, {
signal: abortSignal,
}).then((res: any) => res.json());
},
});
}
bootstrapApplication(App, {
providers: [provideHttpClient()],
});
Stackblitz Demo
版权声明:本文标题:typescript - Why do I need AbortSignal when using the resource API of angular. What is it's use? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741294927a2370762.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论