MCPcopy Create free account
hub / github.com/angular/angular / loadEffect

Method loadEffect

packages/core/src/resource/resource.ts:412–517  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

410 }
411
412 private async loadEffect(): Promise<void> {
413 const extRequest = this.extRequest();
414
415 // Capture the previous status before any state transitions. Note that this is `untracked` since
416 // we do not want the effect to depend on the state of the resource, only on the request.
417 const {status: currentStatus, previousStatus} = untracked(this.state);
418
419 if (extRequest.request === undefined) {
420 // Nothing to load (and we should already be in a non-loading state).
421 return;
422 } else if (currentStatus !== 'loading') {
423 // We're not in a loading or reloading state, so this loading request is stale.
424 return;
425 }
426
427 // Cancel any previous loading attempts.
428 this.abortInProgressLoad();
429
430 // Capturing _this_ load's pending task in a local variable is important here. We may attempt to
431 // resolve it twice:
432 //
433 // 1. when the loading function promise resolves/rejects
434 // 2. when cancelling the loading operation
435 //
436 // After the loading operation is cancelled, `this.resolvePendingTask` no longer represents this
437 // particular task, but this `await` may eventually resolve/reject. Thus, when we cancel in
438 // response to (1) below, we need to cancel the locally saved task.
439 let resolvePendingTask: (() => void) | undefined = (this.resolvePendingTask =
440 this.pendingTasks.add());
441
442 const {signal: abortSignal} = (this.pendingController = new AbortController());
443
444 try {
445 // The actual loading is run through `untracked` - only the request side of `resource` is
446 // reactive. This avoids any confusion with signals tracking or not tracking depending on
447 // which side of the `await` they are.
448 const stream = untracked(() => {
449 return this.loaderFn({
450 params: extRequest.request as Exclude<R, undefined>,
451 abortSignal,
452 previous: {
453 status: previousStatus,
454 },
455 });
456 });
457
458 // If this request has been aborted, or the current request no longer
459 // matches this load, then we should ignore this resolution.
460 const shouldDiscard = () => abortSignal.aborted || untracked(this.extRequest) !== extRequest;
461
462 if (isSignal(stream)) {
463 if (shouldDiscard()) {
464 return;
465 }
466
467 this.state.set({
468 extRequest,
469 status: 'resolved',

Callers

nothing calls this directly

Calls 10

abortInProgressLoadMethod · 0.95
untrackedFunction · 0.90
isSignalFunction · 0.90
signalFunction · 0.90
saveToTransferStateFunction · 0.85
rethrowFatalErrorsFunction · 0.85
encapsulateResourceErrorFunction · 0.85
createDebugNameObjectFunction · 0.70
addMethod · 0.65
setMethod · 0.65

Tested by

no test coverage detected