@ adobe/ 数据
Adobe 数据定向编程库
文档
中断 API 更改
在达到1.0.0之前,小版本的修改可能是API断裂.
数据导向编程
这个库是使用面向数据且功能性编程范式来构建的. 我们更喜欢组成而不是继承,尽可能避免阶级,并强调各种关切的分离.
数据
这个库采用以数据为导向的设计范式,在可行时更喜欢纯功能界面.
为了我们的目的, Data 不可改变的、可串通的物体和原始物—— JSON 以 ReadonlySet, (中文(简体) ), ReadonlyMap,以及 BlobA级 ReadonlyArray 命令(位置有意义);a ReadonlySet 编号 : ReadonlyMap 无命令。 序列化设置/ 带有地图 Data 与 Data.stringify 编号 : Data.parse 页:1 JSON.stringify 制作一个 Set编号 :Map 作为 {}(三); equals 和他们做比较.
为什么数据是不可改变的?
我们更喜欢数据,因为它很容易:
- 序列化
- 淡化
- 检查
- 比较
- 散列轴
- 验证
我们更喜欢不可改变的数据,因为它很容易:
- 原因 关于
- 避免副作用
- 避免防御性复制
- 用于纯函数参数和返回值
- 使用货币
- 纪念结果
- 用作缓存密钥( 字符串)
- 用作缓存值
什么是数据导向设计?
Sanders Mortens在他的ECS FAQ中详尽地阐述了这一点:
https://github.com/SanderMertens/ecs-faq?tab=readme-ov-file#什么-is-数据导向-设计
数据示马斯
当需要运行时间类型信息时,我们使用 JSON Schema。为了避免冗余,我们可以使用 FromSchema 在编译时生成打字符类型.
示例
const Float32Schema = { type: "number", precision: 1 } as const satisfies Schema;
const Float32 = FromSchema<typeof Float32Schema>; // number
我们一定要用 as const 用于计划定义。 没有它,Float32Schema的种类将是 { type: string, precision: number } 改为 { type: "number", precision: 1 } 我们无法用 FromSchema。 。 。 .
标准化数据
当所有包含在其中任何地方的对象密钥都按语法排序时,数据被认为是"正态". 我们包括一个 normalize 用于执行此转换的函数。 当您想要将数据用作缓存密钥时, 这尤其有用 .
const notNormalized = { b: 2, a: 1 };
const normalized = normalize(notNormalized); // { a: 1, b: 2 }
normalize仅使用简单的JSON结构 —— 它不能令人信服Set或者说Map值(没有JSON形式)。 不要喂Set/带有地图Data结束normalize用于缓存键; a 上的键Data.stringify,或者在需要犬形缓存键的地方,用平面阵列/对象建模收藏.
观察器
一个 Observable<T> 是订阅函数,您可以将回调函数传递给它。 您的回调函数可以接受单一类型参数 T。订阅函数返回一个不接受参数的处理函数,并且可以在将来的任何时候调用以取消您的订阅.
您的回调功能 可能 被同步调回(在初始调回之前)0或1次,然后同步调回任何次数.
更多信息见 可观察的 API 文档
可观察类型
/**
* Called to add a new observer to an Observable.
* Returns an Unobserve function that can be called to stop observing the Observable.
*/
export type Observable<T> = (observer: Callback<T>) => Unobserve;
/**
* Callback function called zero or more times with a sequence of values.
* *may* be called back synchronously, immediately when selector function is called.
* *may* also be called back asynchronously later any number of times.
* *may* be called multiple sequential times with the same value.
*/
export type Callback<T> = (value: T) => void;
/**
* Function called to stop observing an Observable.
*/
export type Unobserve = () => void;
一个可观察的,可以被认为是一种承诺,但有一些重要的区别.
- 一个承诺只产生一个单一值,一个可观察值则产生一系列值.
- 约言能以误入歧途而拒绝,可观察者不能拒绝。 (它可以产生类型)
MyResult | MyError虽然.) - 一个承诺只能同步解决 一个可观察的 可能 生成初始结果同步.
- 允许一个可观测器在观察后立即调用 Callback callback 函数,如果它有值的话.
- 一个承诺立即开始执行,可观察者可能懒惰地等待第一个观察者然后采取任何行动.
- 一个可观察的可以不被观察.
可观察创建
这种对可观察器的简单定义使得从各种来源创建它们非常容易.
fromConstant<T>(value: T) => Observable<T>fromPromise<T>(promise: Promise<T>): Observable<T>fromPromiseWithError<T, E extends Error>(promise: Promise<T>): Observable<T | E>fromObservableProperties将具有可观测值的物体转换成具有相应类型的物体的单个可观测对象.
例如:
fromObservables({ a: fromConstant(1), b: fromConstant("s")})
// yields type Observable<{ a: number, b: string }>
fromObservableProperties 只有在每个可观察到的物体都提供了结果后,才会产生结果。 如果某些属性是可选的,则使用 withOptional 更高秩序函数说明如下.
可观察修改
它们也非常容易被修改,以建立更高的可观察性.
为了讨论的目的,让我们使用一个阵列来表示可观测器产生的相继值,第一个要素是任何同步回调和 void 表示没有同步回调 .
我们的 fromConstant(12) 将会屈服 [12] 财务报告和审定财务报表 fromPromise(Promise.resolve(12)) 将会屈服 [void, 12]
这些示例将使用以下形式: QQ高级顺序函数前的序列 QQ序列后.
并删除任何相继等同的值:
[1, 1, 2, 2, 2, 3] => withDeduplicate => [1, 2, 3]
以默认值替换任何未定义的值,包括初始同步值:
[void, 1, 2, undefined, 4] => withDefault(-1) => [-1, 1, 2, -1, 4]
与Map在通知时对每个值应用映射函数:
[void, 1, 2, 3] => withMap(x => x * 2) => [void, 2, 4, 6]
可选转换为 Observable<T> 改为 Observable<T | undefined> 并总是同步响应.
[void, 1, 2, 3, 4] => withOptional => [undefined, 1, 2, 3, 4]
缓存
缓存模块包含与缓存、散列、记忆、存储和检索有关的功能和接口 Blob编号.
这个 memoize 函数和 BlobStore 是缓存子模块中最重要的公共界面. 现将这些情况说明如下。 散列和其他下级函数参见API参考.
这个 memoize 函数可用于缓存昂贵的,决定性的,一个同步的函数,可以取取数据参数并返回数据结果. 除了缓冲结果外,它也阻断了多个带有相同论据的并发呼叫,并使它们等待第一个结果.
布洛布斯托尔
处理很重要 Blob在申请中正确.
这个 BlobStore 界面和相应的 blobStore 导出实例提供了转换的方便方式 Blob变成小JSON的手柄 BlobRefs. 这些 BlobRefs 以后可以转换为 Blob。 。 。 .
Blob属于 blobStore 使用浏览器 buid 在 Cache 存储.
BlobRefs比直接使用blobs有多种优势.
BlobRef标准是:
- 小 json 对象
- 每项决定
Blob基于 mime 类型和内容. - 适用于规模有限的地点的持久性.
- 适合用作缓存密钥
- 适合用作缓存值
示马斯
为了方便,在JSON Schema格式中包含一些标准数据类型计划. 这些类型在描述实体组成部分系统内的组件时最常被使用. 了解了原始数字类型的确切大小和签名性,ECS就可以将这些值存储在严格打包的数组内部. 这使得内存的使用和处理时间更加有效.
实体构成部分系统(ECS)
一个高性能,为TypeScript强烈打入的ECS数据库,灵感来自 花纹。所有应用程序状态被建模为可堆肥插件,所有突变都通过可观察、可撤销的交易来流动.
关于涵盖插件、交易、可观察性、组成和瞬间/瞬间语义的完整指南,见 ECS 读取。 。 。 .
import { Database } from "@adobe/data/ecs";
const myPlugin = Database.Plugin.create({
resources: {
score: { default: 0 as number },
},
transactions: {
addPoints: (t, points: number) => {
t.resources.score += points;
},
},
});
const db = Database.create(myPlugin);
db.observe.resources.score((score) => console.log("Score:", score));
db.transactions.addPoints(10);
什么是ECS?
Sanders Mortens在他的ECS FAQ中详尽地阐述了这一点:
https://github.com/桑德梅尔滕斯/ecs-faq?tab=readme-ov-file#什么-is-ecs
除了标准实体、构成部分和系统定义外,我们还使用这一术语 资源 ——在ECS本身上定义的全球单子值,不附属于任何特定实体.