You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vapor中处理客户端取消的请求?

Vapor服务器捕获客户端取消请求的实现方法

Vapor提供了Request.onCancel方法来监听客户端取消请求的事件(比如前端通过AbortController.abort()触发的请求终止),结合可取消的任务机制,就能在服务器端终止耗时计算操作。以下是具体实现方案:

核心思路

  1. 通过req.onCancel注册回调,当客户端取消请求时触发任务终止逻辑
  2. 耗时计算任务需支持取消:优先使用Swift的Task(天然支持取消),或自定义取消标记

异步计算场景(推荐)

利用Swift的Task封装耗时计算,在计算过程中定期检查取消状态,代码示例:

import Vapor

// 定义请求和响应结构体
struct CalculationInput: Content {
    let text: String
}

struct CalculationResponse: Content {
    let result: String
}

// 注册路由
app.post("api", "dosomething") { req async throws -> CalculationResponse in
    // 解析前端传入的参数
    let input = try req.content.decode(CalculationInput.self)
    
    // 创建可取消的Task执行耗时计算
    let calculationTask = Task { () -> String in
        for step in 0..<1000 {
            // 检查任务是否被取消,若取消则抛出CancellationError
            try Task.checkCancellation()
            
            // 模拟耗时计算步骤
            try? await Task.sleep(nanoseconds: 1_000_000_000)
            print("执行计算步骤:\(step)")
        }
        return "基于'\(input.text)'的计算结果"
    }
    
    // 注册取消回调:前端取消请求时,终止计算Task
    req.onCancel {
        calculationTask.cancel()
    }
    
    // 等待计算结果,处理取消情况
    do {
        let result = try await calculationTask.value
        return CalculationResponse(result: result)
    } catch is CancellationError {
        // 返回客户端取消的自定义状态码(499为Nginx定义的客户端关闭请求状态码,Vapor支持)
        throw Abort(.custom(code: 499, reasonPhrase: "Client Cancelled Request"))
    }
}

同步计算场景

如果你的计算是同步阻塞操作,可通过原子变量维护取消标记,代码示例:

import Vapor
import Atomics

app.post("api", "dosomething") { req throws -> CalculationResponse in
    let input = try req.content.decode(CalculationInput.self)
    // 原子变量存储取消状态,保证线程安全
    let isCancelled = ManagedAtomic<Bool>(false)
    
    // 注册取消回调,标记任务需要终止
    req.onCancel {
        isCancelled.store(true, ordering: .relaxed)
    }
    
    // 执行同步耗时计算
    for step in 0..<1000 {
        if isCancelled.load(ordering: .relaxed) {
            throw Abort(.custom(code: 499, reasonPhrase: "Client Cancelled Request"))
        }
        // 模拟同步耗时操作
        Thread.sleep(forTimeInterval: 1)
        print("执行计算步骤:\(step)")
    }
    
    return CalculationResponse(result: "基于'\(input.text)'的计算结果")
}

关键说明

  • req.onCancel:当客户端断开连接或主动取消请求时,注册的闭包会被调用,此时可触发任务终止逻辑
  • Task.checkCancellation():在异步任务中定期调用该方法,可检测任务是否被取消,若已取消则抛出CancellationError
  • 状态码选择:返回499状态码能明确告知客户端请求已被服务器感知并终止,也可根据需求使用408(请求超时)等标准状态码

内容的提问来源于stack exchange,提问作者silberz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 04:43:25