MCPcopy Index your code
hub / github.com/angular/angular / loadEffect

Method loadEffect

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

Source from the content-addressed store, hash-verified

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