通过protobuf.js与后端进行交互

获取 *.protp文件

后端完成了接口之后,将.proto 文件发给你

编译 *.protp文件

将*.proto文件编译成ts、js文件,这里我是将命令写成一个脚本,运行npm run proto即可编译

1
2
3
{
"proto": "pbjs -t static-module -w commonjs -o ./src/proto/ProtoServices.js ./src/proto/*.proto --no-encode --no-create --no-decode && pbts -o ./src/proto/ProtoServices.d.ts ./src/proto/ProtoServices.js --no-encode --no-create --no-decode"
}

这里其实存在两条命令,分别是:

1
pbjs -t static-module -w commonjs -o ./src/proto/ProtoServices.js ./src/proto/*.proto  --no-encode --no-create --no-decode

1
pbts -o ./src/proto/ProtoServices.d.ts ./src/proto/ProtoServices.js --no-encode --no-create --no-decode

第一句是:通过 ./src/proto/ 路径下的所有proto文件生成 ProtoServices.js 文件,目录在 ./src/proto/ 下

第二句是:通过 新生成的 ProtoServices.js文件生成一份 ProtoServices.d.ts文件,目录在 ./src/proto/ 下

获取泛型

生成了ts之后呢,提取他其中的泛型,这里获取了他三种泛型

  • 发起的请求的泛型
  • 服务器的响应的泛型
  • 回调的对象的泛型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

/** 秘钥对象的泛型 */
interface ICosCredentials {

/** CosCredentials sessionToken */
sessionToken?: (string|null);

/** CosCredentials tmpSecretId */
tmpSecretId?: (string|null);

/** CosCredentials tmpSecretKey */
tmpSecretKey?: (string|null);

}


/** 这个响应的泛型定义 */
interface IGetCosCredentialsResponse {
credentials?: (ICosCredentials|null);
}


/** 定义这个请求的泛型 */
interface IGetCosCredentialsRequest {

/** Hash ID */
hashId?: (string|null);
}

封装底层方法

  • ES7的语法async异步地执行这个函数
  • 接收request参数(已经定义好了request请求的泛型)
  • 返回Promise回调(已经定义好了Promise响应的泛型)
  • 因此,这里我们调用的时候,只需要将data作为参数传递过去,就能拿到服务器的回调
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
async function getCosCredentials(request: IGetCosCredentialsRequest): Promise<IGetCosCredentialsResponse|null> {
try {
const url = getGlobalData('getCosSecretKey');

let cosSecretKey = await Taro.request<IGetCosCredentialsResponse>({
url: url,
data: request,
method: 'POST',
})

console.log(cosSecretKey)

return cosSecretKey.data

} catch (error) {
return null
}
}

客户端使用方法

export一个函数,调用刚刚封装的方法,将{hashId:XXX}作为参数传过去,获取到服务器的返回值赋值给response(响应),然后通过dispatch方法将{getCosSuccess: response}作为参数,用中间件的方法传入Redux(此处省略很多字)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// ⚠️获取COS秘钥
export const getCosSecretKey = () => {

return async (dispatch: ThunkDispatch<RootState, null, AnyAction>, getState: () => RootState) => {

let response = await getCosCredentials({hashId: "XXX"})
console.log(response)
dispatch(getCosSecretSuccess({
getCosSuccess: response
}))
}
}

// 获取cos秘钥成功
export const GET_COS_SECRET_SUCCESS = 'GET_COS_SECRET_SUCCESS'
export interface getCosSecretSuccess {
getCosSuccess: any
}
export const getCosSecretSuccess = createAction(
GET_COS_SECRET_SUCCESS,
(payload: getCosSecretSuccess) => {
return payload
}
)

执行结果

image

彩蛋

这里呢其实我是另辟蹊径了,正确的姿势来说呢,最底层封装好的方法应该是在执行 npm run proto 命令的时候,在生成的 .js 文件中已经封装好了的,在客户端我直接使用就好了的。但是生成的 .js文件有特么七千行代码..= =

不知道是我生成的姿势不对还是怎么样,因此自己封装了一遍底层的函数。以后有更好的方法直接使用 *.js封装的代码的话,会再写一篇博客告诉大家