dehub v0.30.3
Introduction
Note: As the project is not yet fully completed, there is still a risk of code refactoring. Please use with caution. The following only provides simple examples of usage. Detailed documentation will be provided upon official release.
DEHub attempts to be a message-driven library for JavaScript-based clients. It unifies the handling of events and data in all clients by using messages for subscription and processing. This allows all components and business processes in a page to handle business logic in a subscribable manner, and enables access to all registered components through context.
Features:
- Supports component registration
- Allows accessing all registered components in callback functions for event subscriptions
- Supports data subscription
- Supports singleton maintenance for data, ensuring that the same data request is only completed on one instance (this is important)
- Supports data set loading
- Supports serial loading of data sets
Component Registration
test('Register a component', async () => {
// Component tag, used for referencing the component
const tags = { id: 'cmp1' };
// Register the component and use SessionDB to store component information
let comp1 = new DEComp<any>(tags);
await RegComponent(comp1);
// Update the component state
await comp1.update({ a: 1, b: 'abc' });
// Check the updates
expect(comp1.state.a).toBe(2); // X by default, this test will not pass
expect(comp1.state.b).toBe('abc');
});
Event Subscription
To make the 'test' in the component test above pass, you can use 'when' to subscribe to the specified event, and update the value of 'a' to 2 after the 'update' is called.
when({ id: 'cmp1', event: EventNames.StateChanged, stage: EventStage.PostOperation },
(context: EventContext) => {
const comp1 = context.sender as DEComp;
// You can also retrieve the registered component using the following method:
// const comp1 = context.compoents[ObjPath({id:'user1'})];
comp1.update({ a: 2 });
});
Data Subscription
const IdTag = (entity: string, id: string): ObjTag => {
const tag: ObjTag = { entity, id };
return tag;
};
test('Modify and submit data', async () => {
// Data object tag, with user id as 'user1'
const user1Tag = IdTag('user.demo@org0', 'user1');
// Subscribe to the data
const user1Data = DEData(user1Tag);
// Wait for data to finish loading
await sleep(50);
expect(user1Data.get('name')).toBe('Jim');
// Change the data properties, note that the updated values will be stored in 'dirty'
user1Data.set("age", 18);
user1Data.set("name", 'Jim2');
user1Data.set("att1", 'a');
user1Data.set("att2", new Date());
// Wait for the update to complete
await sleep(20);
// Check the updated results, 'get' by default includes the values in 'dirty'
expect(user1Data.get('age')).toBe(18);
expect(user1Data.get('name')).toBe('Jim2');
expect(user1Data.get('att1')).toBe('a');
// 'dirty' stores the unsaved data
expect(user1Data.dirty('age')).toBe(18);
expect(user1Data.dirty('att1')).toBe('a');
// 'original' still stores the original data; note that 'get' will return 'Jim2' at this point
expect(user1Data.original('name')).toBe('Jim');
// Submit the data
await user1Data.submit();
// After submission, the data in 'dirty' will be cleared
expect(user1Data.dirty('age')).toBeUndefined();
// The latest data is now in 'original'
expect(user1Data.original('name')).toBe('Jim2');
}, 2000);
/**
* When loading 'user1', simulate providing the data for 'user1';
*/
when({ entity: 'user.demo@org0', id: 'user1', status: DataStatus.Loading },
(context: EventContext) => {
context.output.data = { name: 'Jim' };
});
/**
* When submitting 'user1', simulate returning the submission result to 'context.output.data';
*/
when({
entity: 'user.demo@org0',
id: 'user1',
event: EventNames.Submit,
status: DataStatus.Uploading,
stage: EventStage.PreOperation
},
(context: EventContext) => {
const sender: DEData = context.sender as DEData;
if (!sender) return;
context.output.data = sender.data;
});
介绍
注意:因项目未列发完成,代码仍有重构风险,谨慎使用,以下仅提供简单的调用示例,待正式发布时提供详细的文档。
DEHub尝试作为基于js的客户端的消息驱动库,将所有客户端的事件与数据变统一由消息的形式进行订阅处理,以便页面中的所有组件及业务流程能够订阅的方式处理业务逻辑,并能够通过上下文访问所有已注册组件。
特性:
- 支持组件注册
- 支持在事件订阅的回调中访问所有注册的组件
- 支持订阅数据
- 支持数据单例维护,所有相同的数据请求只会在一个实例上完成,这个很重要;
- 支持数据集加载
- 支持数据集串行加载
组件的注册
test('注册一个组件', async () => {
//组件标签,可用于引用组件
const tags = { id: 'cmp1' };
//注册组件,并使用SessionDB存储组件信息
let comp1 = new DEComp<any>(tags);
await RegComponent(comp1);
//更新组件state
await comp1.update({ a: 1, b: 'abc' });
//检查更新检查
expect(comp1.state.a).toBe(2); // X 默认,该处无法通过测试
expect(comp1.state.b).toBe('abc');
});
事件订阅
想让上面的组件测试中的test测试通过,可以用when来订阅指定事件,并在更新update后,更新a值为2。
when({ id: 'cmp1', event: EventNames.StateChanged, stage: EventStage.PostOperation },
(context: EventContext) => {
const comp1 = context.sender as DEComp;
// 也可以通过以下方式获取注册的组件;
//const comp1 = context.compoents[ObjPath({id:'user1'})];
comp1.update({ a: 2 });
});
数据订阅
const IdTag = (entity: string, id: string): ObjTag => {
const tag: ObjTag = { entity, id };
return tag;
};
test('数据修改并提交', async () => {
//数据对象标签,用户id为user1
const user1Tag = IdTag('user.demo@org0', 'user1');
//订阅数据
const user1Data = DEData(user1Tag);
//等待数据加载完成
await sleep(50);
expect(user1Data.get('name')).toBe('Jim');
//变更数据属性值,注意:该处更新的值都会进入dirty中;
user1Data.set("age", 18);
user1Data.set("name", 'Jim2');
user1Data.set("att1", 'a');
user1Data.set("att2", new Date());
//等待更新完成
await sleep(20);
//判断更新结果,默认get取值包含了脏数据的值 ;
expect(user1Data.get('age')).toBe(18);
expect(user1Data.get('name')).toBe('Jim2');
expect(user1Data.get('att1')).toBe('a');
//在脏数据dirty保存未提交的数据
expect(user1Data.dirty('age')).toBe(18);
expect(user1Data.dirty('att1')).toBe('a');
//原数据仍保存在original,注意,此时直接用get获取name是Jim2
expect(user1Data.original('name')).toBe('Jim');
//提交数据
await user1Data.submit();
//提交完成后,dirty的数据会被清空
expect(user1Data.dirty('age')).toBeUndefined();
//此时最新数据更新到original中
expect(user1Data.original('name')).toBe('Jim2');
}, 2000);
/**
* 加载user1时,模拟提供user1的数据;
*/
when({ entity: 'user.demo@org0', id: 'user1', status: DataStatus.Loading },
(context: EventContext) => {
context.output.data = { name: 'Jim' };
});
/**
*
* 提交user1时,模拟返回提交成功到context.output.data中;
*/
when({
entity: 'user.demo@org0',
id: 'user1',
event: EventNames.Submit,
status: DataStatus.Uploading,
stage: EventStage.PreOperation
},
(context: EventContext) => {
const sender: DEData = context.sender as DEData;
if (!sender) return;
context.output.data = sender.data;
});
4 months ago
5 months ago
5 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
8 months ago
8 months ago
8 months ago
8 months ago
10 months ago
11 months ago
11 months ago
10 months ago
10 months ago
10 months ago
10 months ago
9 months ago
10 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago