> For the complete documentation index, see [llms.txt](https://ak-scripts.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ak-scripts.gitbook.io/docs/yi-lai/markdown/gong-neng-mo-kuai-dao-chu/hui-tiao-rpccallback.md).

# 回调/RPC（Callback）

## 🔄 Callback（回调/RPC）模块导出文档

### 📋 概述

Callback 模块是 ak-lib 的客户端-服务端 RPC（远程过程调用）系统，提供了统一的回调接口，支持多返回值、超时处理、错误处理等功能。

### 🚀 导出方式

#### 服务端

**方式 1：获取模块对象（推荐）⭐**

```lua
local Callback = exports['ak-lib']:CallbackModule()
```

**方式 2：单独导出函数**

```lua
exports['ak-lib']:RegisterCallback('my:callback', function(source, ...)
    -- 回调逻辑
end)
```

#### 客户端

**方式 1：获取模块对象（推荐）⭐**

```lua
local Callback = exports['ak-lib']:Callback()
```

**方式 2：单独导出函数**

```lua
exports['ak-lib']:TriggerCallback('my:callback', function(result)
    -- 处理结果
end, ...)
```

### 📖 可用导出

#### 服务端

**模块对象方法**

使用 `exports['ak-lib']:CallbackModule()` 获取的对象包含以下方法：

| 方法                   | 说明        | 参数                               | 返回值     |
| -------------------- | --------- | -------------------------------- | ------- |
| `Register(name, cb)` | 注册回调      | `name` (string), `cb` (function) | boolean |
| `Unregister(name)`   | 取消注册回调    | `name` (string)                  | boolean |
| `Has(name)`          | 检查回调是否已注册 | `name` (string)                  | boolean |

**单独导出函数**

| 导出                           | 说明        | 参数                               | 返回值             |
| ---------------------------- | --------- | -------------------------------- | --------------- |
| `CallbackModule()`           | 返回模块对象    | -                                | `AKCallback` 对象 |
| `RegisterCallback(name, cb)` | 注册回调      | `name` (string), `cb` (function) | boolean         |
| `UnregisterCallback(name)`   | 取消注册回调    | `name` (string)                  | boolean         |
| `HasCallback(name)`          | 检查回调是否已注册 | `name` (string)                  | boolean         |

#### 客户端

**模块对象方法**

使用 `exports['ak-lib']:Callback()` 获取的对象包含以下方法：

| 方法                       | 说明      | 参数                  | 返回值 |
| ------------------------ | ------- | ------------------- | --- |
| `Trigger(name, cb, ...)` | 触发服务端回调 | `name`, `cb`, `...` | nil |

**单独导出函数**

| 导出                               | 说明      | 参数                  | 返回值             |
| -------------------------------- | ------- | ------------------- | --------------- |
| `Callback()`                     | 返回模块对象  | -                   | `AKCallback` 对象 |
| `TriggerCallback(name, cb, ...)` | 触发服务端回调 | `name`, `cb`, `...` | nil             |

### 💡 使用示例

#### 服务端：注册回调

```lua
-- 方式 1：使用模块对象（推荐）
local Callback = exports['ak-lib']:CallbackModule()

-- 单返回值
Callback.Register('shop:getPrice', function(source, itemName)
    local price = Items[itemName] and Items[itemName].price or 0
    return price
end)

-- 多返回值（推荐）
Callback.Register('shop:buy', function(source, itemName, count)
    local success = false
    local message = '未知错误'
    local totalPrice = 0
    
    -- 购买逻辑
    local item = Items[itemName]
    if item then
        totalPrice = item.price * count
        if checkMoney(source, totalPrice) then
            success = true
            message = '购买成功'
            removeMoney(source, totalPrice)
            addItem(source, itemName, count)
        else
            message = '金钱不足'
        end
    else
        message = '物品不存在'
    end
    
    -- 返回多个值：成功状态、消息、总价
    return success, message, totalPrice
end)

-- 方式 2：使用单独导出函数
exports['ak-lib']:RegisterCallback('shop:getPrice', function(source, itemName)
    return Items[itemName] and Items[itemName].price or 0
end)
```

#### 客户端：触发回调

**方式 1：简单回调（向后兼容）**

```lua
local Callback = exports['ak-lib']:Callback()

Callback.Trigger('shop:getPrice', function(price)
    print('价格:', price)
end, 'bread')

-- 或使用单独导出函数
exports['ak-lib']:TriggerCallback('shop:getPrice', function(price)
    print('价格:', price)
end, 'bread')
```

**方式 2：多返回值回调**

```lua
local Callback = exports['ak-lib']:Callback()

Callback.Trigger('shop:buy', function(success, message, totalPrice, error)
    if error then
        print('错误:', error)
        return
    end
    
    if success then
        print('成功:', message, '花费:', totalPrice)
    else
        print('失败:', message)
    end
end, 'bread', 5)
```

**方式 3：选项表（推荐 - 新 API）⭐**

```lua
exports['ak-lib']:TriggerCallback('shop:buy', {
    onSuccess = function(success, message, totalPrice)
        if success then
            print('购买成功:', message, '花费:', totalPrice)
        else
            print('购买失败:', message)
        end
    end,
    onError = function(err)
        print('请求错误:', err)
    end,
    timeout = 5000,
    onTimeout = function()
        print('请求超时')
    end
}, 'bread', 5)
```

**方式 4：带超时的简单回调**

```lua
exports['ak-lib']:TriggerCallback('shop:getPrice', function(price)
    print('价格:', price)
end, 'bread', {
    timeout = 3000
})
```

#### 完整示例：商店系统

**服务端**

```lua
local Callback = exports['ak-lib']:CallbackModule()
local FW = exports['ak-lib']:Framework()

Callback.Register('shop:buy', function(source, itemName, count)
    local player = FW.GetPlayer(source)
    if not player then
        return false, '玩家不存在'
    end
    
    local item = Items[itemName]
    if not item then
        return false, '物品不存在'
    end
    
    local totalPrice = item.price * count
    if not FW.HasItem(source, 'money', totalPrice) then
        return false, '金钱不足'
    end
    
    FW.RemoveMoney(source, 'cash', totalPrice, '购买物品')
    FW.AddItem(source, itemName, count)
    
    -- 多返回值：成功状态、消息、总价
    return true, '购买成功', totalPrice
end)
```

**客户端**

```lua
local Callback = exports['ak-lib']:Callback()

function BuyItem(itemName, count)
    Callback.Trigger('shop:buy', {
        onSuccess = function(success, message, totalPrice)
            exports['ak-lib']:Notify({
                type = success and 'success' or 'error',
                message = string.format('%s (花费: $%d)', message, totalPrice or 0)
            })
        end,
        onError = function(err)
            exports['ak-lib']:Notify({
                type = 'error',
                message = '请求失败: ' .. err
            })
        end,
        timeout = 5000,
        onTimeout = function()
            exports['ak-lib']:Notify({
                type = 'error',
                message = '请求超时，请稍后再试'
            })
        end
    }, itemName, count)
end
```

### 📝 API 详细说明

#### 服务端回调函数

回调函数接收 `(source, ...)` 参数：

* `source` (number): 玩家服务器 ID
* `...`: 客户端传递的参数

回调函数可以返回任意值，包括多个值：

```lua
-- 单返回值
return price

-- 多返回值
return success, message, data

-- 无返回值
return  -- 客户端会收到 nil
```

#### 客户端回调选项

**简单回调**

```lua
TriggerCallback(name, callback, ...)
```

**选项表回调（推荐）**

```lua
TriggerCallback(name, {
    onSuccess = function(...) end,  -- 成功回调（接收服务端返回值）
    onError = function(err) end,     -- 错误回调
    timeout = 10000,                 -- 超时时间（毫秒，默认 10000）
    onTimeout = function() end       -- 超时回调
}, ...)
```

**选项说明：**

* `onSuccess`: 成功时调用，接收服务端返回的所有值
* `onError`: 发生错误时调用（回调未注册、执行错误等）
* `timeout`: 超时时间（毫秒），默认 10000ms（10秒），0 = 不超时
* `onTimeout`: 超时时的回调

**向后兼容：** 旧的 `success`、`error`、`timeoutCallback` 键名仍然支持，但会在内部转换为新 API。

### ⚠️ 注意事项

1. **回调名称唯一性**：回调名称应该是唯一的，建议使用 `资源名:功能名` 格式（如 `shop:buy`）。
2. **错误处理**：服务端回调函数中的错误会被自动捕获，不会导致服务器崩溃。
3. **超时设置**：根据操作复杂度合理设置超时时间，避免过长或过短。默认超时 10 秒。
4. **返回值**：服务端回调可以返回任意值，包括 `nil`、`boolean`、`table` 等。
5. **参数传递**：客户端可以传递多个参数给服务端，服务端回调函数按顺序接收。
6. **并发安全**：每个回调请求都有唯一的 `callbackId`，支持并发调用。
7. **多返回值**：服务端回调可以使用多返回值（如 `return true, message, data`），客户端会按顺序接收。
8. **推荐使用新 API**：使用选项表格式（`onSuccess`、`onError`、`onTimeout`），代码更清晰，错误处理更完善。

### 🔗 相关文档

* 回调说明
* Framework 模块导出文档


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ak-scripts.gitbook.io/docs/yi-lai/markdown/gong-neng-mo-kuai-dao-chu/hui-tiao-rpccallback.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
