MCPcopy
hub / github.com/vercel/next.js / addCallback

Method addCallback

packages/next/src/server/after/after-context.ts:55–102  ·  view source on GitHub ↗
(callback: AfterCallback)

Source from the content-addressed store, hash-verified

53 }
54
55 private addCallback(callback: AfterCallback) {
56 // if something is wrong, throw synchronously, bubbling up to the `after` callsite.
57 if (!this.waitUntil) {
58 errorWaitUntilNotAvailable()
59 }
60
61 const workUnitStore = workUnitAsyncStorage.getStore()
62 if (workUnitStore) {
63 this.workUnitStores.add(workUnitStore)
64 }
65
66 const afterTaskStore = afterTaskAsyncStorage.getStore()
67
68 // This is used for checking if request APIs can be called inside `after`.
69 // Note that we need to check the phase in which the *topmost* `after` was called (which should be "action"),
70 // not the current phase (which might be "after" if we're in a nested after).
71 // Otherwise, we might allow `after(() => headers())`, but not `after(() => after(() => headers()))`.
72 const rootTaskSpawnPhase = afterTaskStore
73 ? afterTaskStore.rootTaskSpawnPhase // nested after
74 : workUnitStore?.phase // topmost after
75
76 // this should only happen once.
77 if (!this.runCallbacksOnClosePromise) {
78 this.runCallbacksOnClosePromise = this.runCallbacksOnClose()
79 this.waitUntil(this.runCallbacksOnClosePromise)
80 }
81
82 // Bind the callback to the current execution context (i.e. preserve all currently available ALS-es).
83 // We do this because we want all of these to be equivalent in every regard except timing:
84 // after(() => x())
85 // after(x())
86 // await x()
87 const wrappedCallback = bindSnapshot(
88 // WARNING: Don't make this a named function. It must be anonymous.
89 // See: https://github.com/facebook/react/pull/34911
90 async () => {
91 try {
92 await afterTaskAsyncStorage.run({ rootTaskSpawnPhase }, () =>
93 callback()
94 )
95 } catch (error) {
96 this.reportTaskError('function', error)
97 }
98 }
99 )
100
101 this.callbackQueue.add(wrappedCallback)
102 }
103
104 private async runCallbacksOnClose() {
105 await new Promise<void>((resolve) => this.onClose!(resolve))

Callers 1

afterMethod · 0.95

Calls 9

runCallbacksOnCloseMethod · 0.95
reportTaskErrorMethod · 0.95
bindSnapshotFunction · 0.90
runMethod · 0.65
callbackFunction · 0.50
getStoreMethod · 0.45
addMethod · 0.45
waitUntilMethod · 0.45

Tested by

no test coverage detected