異步調用
===
概述
---
一般情況下,服務端調用API需要等待插件內部執行完成后,才能進行下一步操作。引入異步調用機制,使服務端可以直接跳過等待,由插件在后臺執行,而服務端繼續進行下一步操作,只需要等待插件執行完成后進行回調,或服務端主動查詢調用結果,也可以忽略調用結果。
對于任意API,**均支持被異步調用**。
使用方法
---
例如:
調用API`發送私聊消息「sendPrivateMsg」`
```json
{
"module":"api",
"fun": "sendPrivateMsg",
"qq": 12345,
"msg": "gg"
}
```
* 您可以指定參數`async`為`true`,即
```json
{
"async": true,
"module":"api",
···
}
```
* 也可以在方法名末尾添加`Async`,即
```json
{
"module":"api",
"fun": "sendPrivateMsgAsync",
···
}
```
插件將不會直接返回調用結果
```json
{
"status": 0,
"result": 479,
"request": {
···
}
}
```
而是返回用于**查詢調用結果的標識符`asyncID`**,并且狀態碼(`status`)恒為`0`(success)
```json
{
"status": 0,
"asyncID": 6469864,
"request": {
···
}
}
```
您也可以指定參數`async`為自定義標識符,如
```json
{
"async": 2333,
"module":"api",
···
}
```
但**不建議這樣做**,因為在調用結果被服務端取回前,每個標識符都是唯一的,也就是存在沖突。
因此,在標識符產生沖突后,插件會強制生成唯一的隨機標識符。
獲取調用結果
---
對于任意的異步調用,插件會保留調用結果以供查詢,
您可調用`async`模塊下的`get`方法,使用標識符作為參數`id`的值獲取調用結果
```json
{
"module": "async",
"fun": "get",
"id": 6469864
}
```
如果獲取成功,狀態碼(`success`)為`0`,并且響應(`response`)的值為調用結果,該值與通過非異步方式調用結果一致。
```json
{
"status": 0,
"response": {
"status": 0,
"result": 478,
"request": {
···
}
},
"request": {
"module": "async",
"fun": "get",
"id": 6469864
}
}
```
忽略調用結果
---
您可以選擇不查詢調用結果,這并不會有任何影響,但強烈建議您在**調用時指定參數`nonCall`為`true`**,
```json
{
"fun": "sendPrivateMsgAsync",
"nonCall": true,
···
}
```
這樣插件就不會申請資源用于存儲調用結果。
將調用結果回調
---
如果您不想服務端主動查詢調用結果,也可**指定參數`callback`為回調URL**。
```json
{
"fun": "sendPrivateMsgAsync",
···
"callback": "http://example.com/callback"
}
```
調用完成后,插件會使用HTTP協議的**POST方法**將調用結果回傳給指定的URL。
```
POST /callback HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Content-Type: application/json; charset=UTF-8
Accept: application/json
Accept-Charset: utf-8
Accept-Language: zh-cn
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Content-Length: 287
Host: example.com
{
"status": -23,
"errmsg": "找不到與目標QQ的關系,消息無法發送",
"asyncID": 44482768,
"request": {
···
}
}
```
如您所見,**回調數據為`json`格式,`UTF-8`編碼,并未進行`URL`編碼**,和非異步調用結果相似,僅僅是多了`asyncID`。
您也可**在`callback`中指定更多參數**,以適應不同的業務場景。
```json
{
"fun": "sendPrivateMsgAsync",
···
"callback": {
????????"url": "http://example.com/callback",
????????"header": "X-Token:?This?is?value.\nX-Forward-To:?db.local",
????????"cookie": "a=b;?b=c;?c=d",
????????"proxy": "127.0.0.1:8888",
"paramA": "valueA",
"paramB": "valueB"
????}
}
```
| 參數 | 可選 | 說明 |
| :-: | :-: | --- |
| `url` | **×** | 回調URL |
| `header` | √ | HTTP請求頭部,多個值請用`\n`換行 |
| `cookie` | √ | HTTP請求Cookie |
| `proxy` | √ | 代理地址,格式:`ip:port` |
**其余參數將作為URL參數進行傳遞**,
> 本示例中存在參數`paramA`與`paramB`,
> 因此最終請求的URL為`http://example.com/callback?paramA=valueA&¶mB=valueB`。
對于主動連接
---
> 在本小節,主動連接特指**插件通過HTTP協議向服務端發送數據**的連接行為。
在主動連接中異步調用API并無特殊之處,但因為其可一次調用多條API命令,所以**指定參數`async`為自定義標識符時尤其需要注意其唯一性**。當然,如果標識符不唯一,插件同樣會生成一個唯一標識符,但如果服務端在回調時依賴該自定義標識符,則您需要特別注意這點。
如果在一條API命令中**指定`callback`參數**,即設置回調URL,則后續調用的**所有命令都會進行回調**,您可指定參數`nonCall`解除回調。
一些補充
---
* 異步調用主要用于設置操作(即`set`、`send`開頭的API),
對于用于獲取數據(即`get`開頭的API),盡可能不使用異步調用,除非設置回調URL回傳數據,否則這種操作是無意義。
* 如果**指定參數`callback`或`nonCall`**,則視為異步調用,無論是否指定參數`async`。