# 超时配置与流式响应｜Creght AI 编程指南

> Creght Func 的超时与流式响应：invoke 的 timeoutMs 该设在哪、300 秒执行上限与返回体积限制、context deadline exceeded 的排查顺序，以及原生 fetch + SSE 的完整解析实现。

[![Creght](https://ugc.talizen.com/_assets/site/2061660904709165056/1780797461299__creght_logo.png)API for AI](/)

[查看 llms.txt](/llms.txt)

概览

- [Creght AI 编程指南](/api.md)

AI 可发现性

- [如何优化 llms.txt](/api/optimize-llms-txt.md)

站点配置

- [实现基于域名的多语言路由](/api/domain-locale-routing.md)

后端

- [在服务端调用外部 API 并管理缓存](/api/ssr-external-api-cache.md)
- [使用 Func 构建站点后端能力](/api/func-backend.md)
- [JSON 表：定义、读写与查询](/api/func-json-tables.md)
- [上传文件：直传与 Func 内生成](/api/func-assets-upload.md)
- [超时配置与流式响应](/api/func-timeout-streaming.md)
- [使用 Func 接入支付宝电脑网站支付](/api/func-alipay-payment.md)

集成

- [使用集成发送邮件与验证码](/api/func-email-integration.md)
- [使用集成接入支付宝支付](/api/func-alipay-integration.md)

登录与用户

- [注册时验证邮箱](/api/auth-verified-registration.md)
- [实现找回密码与修改密码](/api/auth-password-reset.md)
- [在 Func 里实现登录](/api/auth-func-login.md)
- [在 Func 里查询用户](/api/func-user-directory.md)

本页目录

- [超时配置](#timeout)
- [诊断 context deadline exceeded](#diagnosis)
- [原生 Fetch + SSE 流式响应](#streaming)
- [流式不是后台任务](#not-background)
- [验收清单](#checklist)

后端/超时配置与流式响应

# 超时配置与流式响应

invoke 默认 5 秒、执行上限 300 秒、返回体积约 1 MiB——长任务撞的到底是哪一条，以及 context deadline exceeded 的诊断顺序。含 ctx.sse.send 加原生 Fetch 的完整 SSE 解析写法，和「流式不是后台任务」这条边界。

复制 Markdown 链接

普通 `invoke()` 等的是一个完整 JSON 结果， **默认 5 秒** 就超时。模型生成、慢的第三方接口和需要边算边显示的场景都会撞上这条线。这篇讲两件事：把超时设在对的地方，以及用原生 Fetch + SSE 做有界的增量输出。

**智能体目标**

超时是 **调用端** 的参数，按任务实际耗时设置并在真实页面路径上验证。增量输出用 `ctx.sse.send` 加原生 `fetch`，不要发明脱离请求继续执行的后台任务。

## 超时配置

`invoke` 默认超时是 **5 秒**，Func runner 的默认最大执行时间是 **300 秒**。有界的模型生成或第三方请求可以在调用端设置更长时间；这不意味着可以启动脱离请求继续执行的后台任务。

```typescript
const result = await invoke('image.generate', input, {
  timeoutMs: 120000,
})
```

同时生效的还有几条硬限制，它们不会因为放宽超时而变化：

| 限制 | 值 |
| --- | --- |
| `invoke` 默认超时 | 5 秒，由调用端 `timeoutMs` 覆盖 |
| 单次执行上限 | 300 秒 |
| Func 返回体积 | 约 1 MiB，超出即失败——这是"把整表读出来返回"最先撞到的墙 |
| Func 代码体积 | 约 256 KiB |

### 诊断 context deadline exceeded

遇到 `context deadline exceeded` 或 `context timeout` 时，按顺序做三件事：

1. 先检查页面实际传给 `invoke(..., { timeoutMs })` 的值。绝大多数情况问题在这里——调用端还是默认的 5 秒。
2. 用相同输入、相同模型提高超时重试。 `creght func run --timeout_ms` / `run_func.timeout_ms` **只影响这次自测**，跑通不能证明生产路径也会通，跑不通也不能证明平台有同样的硬限制。
3. 如果提高后成功，就提高生产调用端的 `timeoutMs`，并在真实页面上验证一次完整路径。

> 不要把缩短输出、降低 `max_tokens`、切换模型或供应商、创建新表、伪造后台任务当成超时修复。这些都会改变功能本身，而问题只是一个数字设小了。

## 原生 Fetch + SSE 流式响应

需要有界增量输出时，服务端通过 `ctx.sse.send` 发事件，浏览器直接使用原生 `fetch` 和 `ReadableStream`； **不需要 `invokeStream` 这样的封装**。

```typescript
// /backend/func/writer.ts
export async function main(input, ctx) {
  ctx.sse.send('token', { text: 'Hello' })
  ctx.sse.send('token', { text: ' world' })
  return { ok: true }
}
```

浏览器侧要自己解析 SSE 帧。关键是 `reader.read()` 返回的是 **任意字节块**，不保证一个块正好是一个事件：

```typescript
const response = await fetch('/func/writer?stream=1&timeout_ms=120000', {
  method: 'POST',
  headers: {
    Accept: 'text/event-stream',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(input),
})
if (!response.ok || !response.body) throw new Error('Func stream failed')

const reader = response.body.getReader()
const decoder = new TextDecoder()
let buffer = ''

while (true) {
  const { done, value } = await reader.read()
  if (done) break
  buffer += decoder.decode(value, { stream: true })

  const frames = buffer.split(/\r?\n\r?\n/)
  buffer = frames.pop() || ''
  for (const frame of frames) {
    const event = frame.match(/^event:\s*(.+)$/m)?.[1]
    const data = frame.match(/^data:\s*(.+)$/m)?.[1]
    if (event === 'token' && data) {
      output += JSON.parse(data).text
    }
  }
}
```

- 必须 **跨读取缓存**，并且只按空行分隔 SSE frame，最后一段不完整的留在缓冲区里等下一块。
- 流式路径用 URL 上的 `?stream=1&timeout_ms=...`，不是 `invoke()` 的选项。
- 平台负责发最终的 `done` 或 `error` 事件，两个都要处理。
- **第一个事件发出后不能再修改 Cookie**：响应头此时已经提交。需要设置会话或 Cookie 的动作要放在第一次 `send` 之前。
- 调用超时同样生效，流式不等于无限流。

## 流式不是后台任务

SSE 让用户更早看到进度，但它仍然是 **一次请求内** 的输出。Func 不支持脱离请求继续执行：没有 `setTimeout`/ `setInterval`，没有任务队列，也没有"先返回再慢慢算"。

如果一件事确实超过 300 秒，就把它拆成用户可见的多步：每一步是一次有界调用，中间状态落在 [JSON 表](/api/func-json-tables.md) 里，由页面驱动下一步——而不是让一次调用挂在那里。

## 验收清单

- 长耗时调用在生产页面上设置了与实际耗时匹配的 `timeoutMs`，并验证过真实路径。
- 返回值没有夹带大段内容，没有接近 1 MiB 的返回体。
- SSE 解析跨读取缓存，按空行切帧，处理了 `done` 与 `error`。
- 需要设置 Cookie 的逻辑在第一个 SSE 事件之前完成。
- 没有用计时器、轮询或伪造的后台任务来绕过超时。

**完成标准**

超时值来自对任务耗时的判断而不是试错，流式输出在真实页面上完整跑通首个事件、中途事件与结束事件三段，超时失败时页面有明确的用户可见状态。

![Creght](https://ugc.talizen.com/_assets/site/2061660904709165056/1780797461299__creght_logo.png)

此网站使用 [Creght](/) 创建

![微信客服](https://fsu.creght.com/site/2066727200882692096/1785119134612__image.png)

微信客服

## 链接

- [价格](/price.md)
- [解决方案](/solution.md)
- [客户案例](/customers.md)
- [帮助中心](/help.md)
- [联系我们](/contact.md)
- [更新记录 & 博客](/blogs.md)
- [退款说明](/tuikuan.md)

## 资源

- [全部资源](/resources.md)
- [模板](/templates.md)
- [组件库](https://creghtlib.site.creght.com)
- [动效库](/design/effects.md)
- [Figma to Creght](/figma2creght.md)
- [API](/api.md)

## 产品对比

- [对比上线了](/creght-vs-sxl.md)
- [对比凡科建站](/creght-vs-fkw.md)
- [自己写代码 vs Creght](/compare/self-coding.md)
- [外包 vs 自己做](/compare/outsourcing.md)

## 协议

- [用户协议](/legal/terms.md)
- [隐私政策](/legal/privacy.md)
- [可接受使用政策](/legal/acceptable-use.md)

## 社交媒体

- [小红书](https://www.xiaohongshu.com/user/profile/5a38606811be10715f4895b6)
- [哔哩哔哩](https://space.bilibili.com/513308095)

[蜀ICP备2023038192号-2](https://beian.miit.gov.cn)
