feat: websocket 支持设置初始提交数据 (#2766)

This commit is contained in:
吴多益 2021-10-27 13:50:41 +08:00 committed by GitHub
parent ed92a2b1be
commit ad0d941031
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 78 additions and 28 deletions

View File

@ -345,7 +345,6 @@ Service 支持通过 WebSocket 获取数据,只需要设置 ws由于无示
```json
{
"type": "service",
"api": "/api/mock2/page/initData",
"ws": "ws://localhost:8777",
"body": {
"type": "panel",
@ -355,6 +354,30 @@ Service 支持通过 WebSocket 获取数据,只需要设置 ws由于无示
}
```
> 1.3.5 及以上版本
或者是对象的方式支持配置初始 `data`,这个 data 会在建立连接时发送初始数据
```json
{
"type": "service",
"ws": {
"url": "ws://localhost:8777?name=${name}",
"data": {
"name": "${name}"
}
},
"body": {
{
"label": "名称",
"type": "input-text",
"value": "name",
"name": "amis"
}
}
}
```
可以只设置 ws通过 ws 来获取所有数据,也可以同时设置 api 和 ws让 api 用于获取全部数据,而 ws 用于获取实时更新的数据。
后端实现示例,基于 [ws](https://github.com/websockets/ws)
@ -379,11 +402,18 @@ ws.on('connection', function connection(ws) {
WebSocket 客户端的默认实现是使用标准 WebSocket如果后端使用定制的 WebSocket比如 socket.io可以通过覆盖 `env.wsFetcher` 来自己实现数据获取方法,默认实现是:
> 1.3.5 及以上版本修改了 ws 类型,将之前的字符串改成了对象的方式,会有两个参数 url 和 body
```javascript
wsFetcher(ws, onMessage, onError) {
if (ws) {
const socket = new WebSocket(ws);
socket.onmessage = (event: any) => {
const socket = new WebSocket(ws.url);
socket.onopen = event => {
if (ws.body) {
socket.send(JSON.stringify(ws.body));
}
};
socket.onmessage = event => {
if (event.data) {
onMessage(JSON.parse(event.data));
}

View File

@ -74,11 +74,16 @@ export interface RenderSchemaFilter {
(schema: Schema, renderer: RendererConfig, props?: any): Schema;
}
export interface wsObject {
url: string;
body?: any;
}
export interface RenderOptions {
session?: string;
fetcher?: (config: fetcherConfig) => Promise<fetcherResult>;
wsFetcher?: (
ws: string,
ws: wsObject,
onMessage: (data: any) => void,
onError: (error: any) => void
) => void;
@ -234,8 +239,13 @@ const defaultOptions: RenderOptions = {
// 使用 WebSocket 来实时获取数据
wsFetcher(ws, onMessage, onError) {
if (ws) {
const socket = new WebSocket(ws);
socket.onmessage = (event: any) => {
const socket = new WebSocket(ws.url);
socket.onopen = event => {
if (ws.body) {
socket.send(JSON.stringify(ws.body));
}
};
socket.onmessage = event => {
if (event.data) {
onMessage(JSON.parse(event.data));
}

View File

@ -7,7 +7,7 @@ import {filter, evalExpression} from '../utils/tpl';
import cx from 'classnames';
import Scoped, {ScopedContext, IScopedContext} from '../Scoped';
import {observer} from 'mobx-react';
import {isApiOutdated, isEffectiveApi} from '../utils/api';
import {buildApi, isApiOutdated, isEffectiveApi} from '../utils/api';
import {Spinner} from '../components';
import {autobind, isEmpty, isVisible, qsstringify} from '../utils/helper';
import {
@ -168,7 +168,7 @@ export default class Service extends React.Component<ServiceProps> {
if (this.socket) {
this.socket.close();
}
this.socket = store.fetchWSData(props.ws, this.afterDataFetch);
this.socket = this.fetchWSData(props.ws, store.data);
}
if (props.defaultData !== prevProps.defaultData) {
@ -216,10 +216,39 @@ export default class Service extends React.Component<ServiceProps> {
}
if (ws) {
this.socket = store.fetchWSData(ws, this.afterDataFetch);
this.socket = this.fetchWSData(ws, store.data);
}
}
// 因为有异步,这里
fetchWSData(ws: string | Api, data: any) {
const {env, store} = this.props;
const wsApi = buildApi(ws, data);
env.wsFetcher(
wsApi,
(data: any) => {
let returndata = data;
if ('status' in data && 'data' in data) {
returndata = data.data;
if (data.status !== 0) {
store.updateMessage(data.msg, true);
env.notify('error', data.msg);
return;
}
}
store.updateData(returndata, undefined, false);
store.setHasRemoteData();
// 因为 WebSocket 只会获取纯数据,所以没有 msg 之类的
this.afterDataFetch({ok: true, data: returndata});
},
(error: any) => {
store.updateMessage(error, true);
env.notify('error', error);
}
);
}
afterDataFetch(result: any) {
// todo 应该统一这块
// 初始化接口返回的是整个 response

View File

@ -140,24 +140,6 @@ export const ServiceStore = iRendererStore
}
});
const fetchWSData = (ws: string, afterDataFetch: (data: any) => any) => {
const env = getEnv(self);
env.wsFetcher(
ws,
(data: any) => {
self.updateData(data, undefined, false);
setHasRemoteData();
// 因为 WebSocket 只会获取纯数据,所以没有 msg 之类的
afterDataFetch({ok: true, data: data});
},
(error: any) => {
updateMessage(error, true);
env.notify('error', error);
}
);
};
const setHasRemoteData = () => {
self.hasRemoteData = true;
};
@ -505,7 +487,6 @@ export const ServiceStore = iRendererStore
markBusying,
fetchInitData,
fetchData,
fetchWSData,
reInitData,
updateMessage,
clearMessage,