藏头诗生成:错误处理与超时(ret_code / showapi_res_code / 30s 超时)
# 藏头诗生成:错误处理与超时(ret_code / showapi_res_code / 30s 超时)
> 接口/接入点:藏头诗生成(apiCode=950,接入点 950-1)· 免费 · 返回格式 JSON · 适用人群:已接入开发者、架构师 · 阅读时间:7 分钟
## 核心要点
- 成功判定看业务层 `showapi_res_body.ret_code == "0"`,**不是**外层 `showapi_res_code`。
- 文档**未给出** ret_code 的具体枚举值,只说明"非 0 即失败",代码仅做 `!= "0"` 判断。
- OpenAPI 标注 `x-read-timeout:30` / `x-connect-timeout:30`,**代码超时设 30 秒**;重试加指数退避。
## Why:不处理好错误,免费接口也会拖垮业务
网络抖动、档位耗尽、参数异常都会让调用失败。正确区分"外层网关"与"业务层"失败、设好超时与退避,才能在生产环境稳定运行。
## What:错误相关字段
| 字段 | 层级 | 含义 |
|------|------|------|
| `showapi_res_code` | 系统级 | 网关整体状态码(0 一般表示网关正常收到) |
| `showapi_res_error` | 系统级 | 网关级错误信息 |
| `showapi_res_body.ret_code` | 业务层 | `0` 成功,其他值失败(无枚举,仅"非0即失败") |
| `showapi_res_id` | 系统级 | 请求唯一标识,排查用 |
超时(来自 OpenAPI):读取 30s、连接 30s。
## How:健壮调用模板(含退避)
**Python(30s 超时 + 指数退避)**
```python
import requests, time
url = "https://route.showapi.com/950-1"
params = {"appKey": "YOUR_APPKEY"}
data = {"num": "5", "type": "1", "yayuntype": "1", "key": "易源接口"}
for attempt in range(3):
try:
r = requests.post(url, params=params, data=data, timeout=30)
res = r.json()
body = res.get("showapi_res_body", {})
if body.get("ret_code") == "0":
print("\n".join(body["list"]))
break
else:
print("业务失败:", res.get("showapi_res_error"), "ret_code=", body.get("ret_code"))
break
except requests.RequestException as e:
wait = 2 ** attempt
print(f"请求异常 {e},{wait}s 后重试({attempt+1}/3)")
time.sleep(wait)
```
**Node.js(fetch + AbortSignal 30s + 退避)**
```javascript
const url = "https://route.showapi.com/950-1?appKey=YOUR_APPKEY";
const body = new URLSearchParams({ num: "5", type: "1", yayuntype: "1", key: "易源接口" });
for (let i = 0; i < 3; i++) {
try {
const resp = await fetch(url, { method: "POST", body, signal: AbortSignal.timeout(30000) });
const res = await resp.json();
const b = res.showapi_res_body;
if (b.ret_code === "0") { b.list.forEach((p) => console.log(p)); break; }
console.error("业务失败:", res.showapi_res_error, "ret_code=", b.ret_code); break;
} catch (e) {
const wait = 2 ** i;
console.error(`请求异常 ${e},${wait}s 后重试(${i+1}/3)`);
await new Promise((r) => setTimeout(r, wait));
}
}
```
**cURL(显式 30s 超时)**
```bash
curl -X POST "https://route.showapi.com/950-1?appKey=YOUR_APPKEY" \
--max-time 30 \
-d "num=5&type=1&yayuntype=1&key=%E6%98%93%E6%BA%90%E6%8E%A5%E5%8F%A3"
```
## 返回示例与解析
失败示例(业务层):
```json
{
"showapi_res_code": 0,
"showapi_res_error": "",
"showapi_res_body": { "ret_code": "1", "list": [] }
}
```
注意外层 `showapi_res_code=0` 但业务 `ret_code` 非 0 —— 必须判业务层,否则会误判成功。具体 ret_code 取值文档未枚举,只按"非 0 即失败"处理,错误信息读 `showapi_res_error`。
## 进阶 / 边界
- **不按 ret_code 具体值分支**:因文档未给枚举,硬编 -1/-2 等语义会误导,统一 `!= "0"` 判定。
- **档位耗尽**:免费接口超档次限制会失败,见[免费档位与成本](https://www.showapi.com/guides/cangtoushi-cache-cost-950)。
- **批量场景**:循环调用时退避+缓存结合,避免雪崩。
## FAQ
**Q1:为什么外层 code=0 还失败?** 外层只表示网关收到,业务成败看 `showapi_res_body.ret_code`。
**Q2:ret_code=1 是什么意思?** 文档未定义具体码值含义,仅"非0即失败",原因看 showapi_res_error。
**Q3:超时设多少?** 按 OpenAPI 标注设 30 秒(连接/读取各 30s),不要用默认 10s。
**Q4:重试会重复计费吗?** 免费接口一般不计费,但重试消耗档位额度,务必加退避与缓存。
## 相关能力 / 下一步阅读
- [藏头诗生成:返回字段全解(list / ret_code / showapi_res_*)](https://www.showapi.com/guides/cangtoushi-response-fields-950)
- [藏头诗生成:免费档位与积分兑换,如何控制调用成本](https://www.showapi.com/guides/cangtoushi-cache-cost-950)
- **本系列共 12 篇**:查看[藏头诗生成指南总目录](https://www.showapi.com/guides/cangtoushi-guides-950)