Edit

onClose()

Environment: server & client.

You can listen when Telefunc streams close to:

  • Clear resources
    ⚠️

    Make sure you always clear long-lived resources (setInterval, an event subscription, a DB cursor, an upstream stream, ...).

  • Handle errors
  • Cancel in-flight work
APISideFires when
context.onClose(cb)serverall stream closes
channel.onClose(cb)client & serverthe one channel closes
context.signal (AbortSignal)serverall stream closes

The listeners fire regardless of why the stream closed — whether all streams finished, the client stopped using the streams, you closed them manually, the client disconnected, or an error occurred.

Every stream eventually ends — at the latest when the client disconnects (e.g. the user navigates away from your website), but usually sooner: when the client stops using the stream, you close it manually, the network connection is permanently lost (and couldn't be recovered), or an error occurs.

See API > close() to manually close streams.

context.onClose()

Environment: server.

The onClose() hook (defined on context) is called once all the streams opened by a telefunction call have closed.

To listen for a single channel to close, use channel.onClose() instead.

// AiChat.telefunc.js
// Environment: server
 
import { getContext } from 'telefunc'
 
export async function* onAiPrompt(prompt) {
  const { onClose } = getContext()
  onClose((err) => {
    // Release resources, handle errors, cancel upstream work, ...
  })
  for await (const message of ai.streamText({ prompt })) {
    yield message
  }
}
// AiChat.telefunc.ts
// Environment: server
 
import { getContext } from 'telefunc'
 
export async function* onAiPrompt(prompt: string) {
  const { onClose } = getContext()
  onClose((err) => {
    // Release resources, handle errors, cancel upstream work, ...
  })
  for await (const message of ai.streamText({ prompt })) {
    yield message
  }
}
// AiChat.telefunc.js
// Environment: server
 
import { getContext } from 'telefunc'
 
export async function* onAiPrompt(prompt) {
  const { onClose } = getContext()
 
  // Stop the upstream AI request when the client disconnects or stops reading
  const controller = new AbortController()
  onClose(() => controller.abort())
 
  const stream = await ai.streamText({ prompt, signal: controller.signal })
  for await (const message of stream) {
    yield message
  }
}
// AiChat.telefunc.ts
// Environment: server
 
import { getContext } from 'telefunc'
 
export async function* onAiPrompt(prompt: string): AsyncGenerator<string> {
  const { onClose } = getContext()
 
  // Stop the upstream AI request when the client disconnects or stops reading
  const controller = new AbortController()
  onClose(() => controller.abort())
 
  const stream = await ai.streamText({ prompt, signal: controller.signal })
  for await (const message of stream) {
    yield message
  }
}

channel.onClose()

Environment: server & client.

The onClose() hook defined on a new Channel() instance is called when that channel closes.

To listen for all streams to close, use context.onClose() instead.

channel.onClose((err) => {
  // ...
})

The channel.onClose() hook can be used on both the server- and client-side.

context.signal

Environment: server.

The context object includes a signal (AbortSignal) that aborts when the telefunction call closes.

The signal fires at the same time as onClose().

Pass it to any API that accepts an AbortSignal (fetch(), database clients, etc.) to cancel in-flight work:

// SomeComponent.telefunc.js
// Environment: server
 
import { getContext } from 'telefunc'
 
export async function onLoad() {
  const { signal } = getContext()
  const response = await fetch(
    'https://api.example.com/data',
    // Cancel the request, e.g. when the client disconnects
    { signal }
  )
  return response.json()
}
// SomeComponent.telefunc.ts
// Environment: server
 
import { getContext } from 'telefunc'
 
export async function onLoad() {
  const { signal } = getContext()
  const response = await fetch(
    'https://api.example.com/data',
    // Cancel the request, e.g. when the client disconnects
    { signal }
  )
  return response.json()
}

See also