使用Nginx njs异步Promise编写边缘逻辑需全程采用原生异步API(如fetch、subrequest、setTimeout),禁用同步调用;Promise链须完整返回并显式处理,主动设置超时与降级,且仅在顶层安全设置响应。

利用 Nginx njs 的异步 Promise 机制编写不阻塞事件循环的边缘逻辑,核心在于:**所有耗时操作必须走 njs 提供的异步 API(如 subrequest、fetch、setTimeout),避免同步 I/O 或长循环;Promise 链必须完整返回并由 njs 运行时调度,不能在回调中隐式丢弃或阻塞等待。**
只用 njs 原生异步接口,禁用同步阻塞调用
njs 不支持 Node.js 风格的 fs.readFileSync 或 JSON.parse 大文本(虽语法合法但会阻塞)。任何外部交互都必须使用其内置异步方法:
-
发 HTTP 请求:用
r.fetch(url, options)(推荐)或r.subrequest(uri, options),二者均返回 Promise,不阻塞主线程 -
延时/定时:用
setTimeout(() => {}, ms),而非while(Date.now() 这类忙等待 -
解析 JSON:若数据来自
fetch响应体,直接用res.json()(返回 Promise);避免对大字符串调用JSON.parse(str)—— 虽非 I/O,但长字符串解析仍占用事件循环时间,可考虑流式预检或拆分处理
Promise 链必须显式返回并 await(或 then),不可“丢失”
njs 中未被 await 或未接 then/catch 的 Promise 会被静默忽略,且其后续逻辑不会被调度,容易造成逻辑跳过或状态不一致:
- ✅ 正确写法:
return r.fetch(...).then(res => res.json()).then(data => { ... }) - ✅ 推荐写法(njs 支持顶层 await):
const data = await r.fetch(...).then(r => r.json()); - ❌ 错误写法:
r.fetch(...).then(...);—— Promise 被创建后无消费者,njs 不会执行其回调
边缘逻辑需主动控制超时与降级,避免 Promise 悬停
njs 的 Promise 无自动超时机制。若上游服务响应慢或失败,未设限的 fetch 可能长期挂起,拖慢整个请求生命周期:
- 用
Promise.race包裹 fetch + 定时 reject:const controller = new AbortController();<br>const timeout = setTimeout(() => controller.abort(), 800);<br>const res = await r.fetch(url, { signal: controller.signal });<br>clearTimeout(timeout); - 对 subrequest,可通过
vars或共享内存(shared_dict)缓存降级响应,避免每次失败都重试 - 所有
catch分支必须返回有效值(如空对象、默认 header),防止因异常导致后续 njs 逻辑中断
避免在 Promise 回调中修改 request 对象的非异步安全字段
njs 的 r 对象部分属性(如 r.headersOut、r.return)只能在主请求上下文或特定钩子中安全设置。在 fetch().then() 回调里直接写 r.return(200, "...") 可能无效或报错:
- ✅ 安全做法:在 Promise 解析后,统一在顶层函数末尾调用
r.return或r.headersOut;或用r.internalRedirect跳转到预定义 location 处理响应 - ✅ 更健壮方式:将业务逻辑结果存在
r.variables.my_result,再通过auth_request或content_by_njs配合 location 做最终输出











