API 校验
Entity.validate() 会在规范化和反规范化过程中被调用。返回 undefined 表示没有错误;如果有错误,则返回字符串形式的错误信息。
字段检查
校验发生在 Entity.process() 之后、Entity.fromJS() 之前,因此它操作的是 POJO,而不是类的实例。
这里我们可以确保包含 title 字段,并且其类型符合预期。
Fixtures
GET /article/1
{"id":"1","title":"first"}
GET /article/2
{"id":"2"}
GET /article/3
{"id":"3","title":{"complex":"second","object":5}}
▶api/Article
import { Entity, RestEndpoint } from '@data-client/rest'; export class Article extends Entity { id = ''; title = ''; static validate(processedEntity) { if (!Object.hasOwn(processedEntity, 'title')) return 'missing title field'; if (typeof processedEntity.title !== 'string') return 'title is wrong type'; } } export const getArticle = new RestEndpoint({ path: '/article/:id', schema: Article, });
▶ArticlePage
结果
Store▶
全部字段检查
validateRequired() 可用于检查所有已定义的字段是否都存在。
Fixtures
GET /article/1
{"id":"1","title":"first"}
GET /article/2
{"id":"2"}
GET /article/3
{"id":"3","title":{"complex":"second","object":5}}
▶api/Article
import { Entity, RestEndpoint, validateRequired } from '@data-client/rest'; export class Article extends Entity { id = ''; title = ''; static validate(processedEntity) { return validateRequired(processedEntity, this.defaults); } } export const getArticle = new RestEndpoint({ path: '/article/:id', schema: Article, });
▶ArticlePage
结果
Store▶
部分结果
校验的另一个绝佳用途是混合使用返回不完整对象的 endpoint。当某些字段占用大量带宽,或者对后端来说计算开销很大时,这通常很有用。
可以考虑使用 validateRequired 来减少代码量。
Fixtures
GET /article
[{"id":"1","title":"first"},{"id":"2","title":"second"}]
GET /article/1
{"id":"1","title":"first","content":"long","createdAt":"2011-10-05T14:48:00.000Z"}
GET /article/2
{"id":"2","title":"second","content":"short","createdAt":"2011-10-05T14:48:00.000Z"}
▶api/Article
import { Entity, RestEndpoint } from '@data-client/rest'; import { Temporal } from 'temporal-polyfill'; export class ArticlePreview extends Entity { id = ''; title = ''; static key = 'Article'; } export const getArticleList = new RestEndpoint({ path: '/article', schema: [ArticlePreview], }); export class ArticleFull extends ArticlePreview { content = ''; createdAt = Temporal.Instant.fromEpochMilliseconds(0); static schema = { createdAt: Temporal.Instant.from, }; static validate(processedEntity) { if (!Object.hasOwn(processedEntity, 'content')) return 'Missing content'; } } export const getArticle = new RestEndpoint({ path: '/article/:id', schema: ArticleFull, });
▶ArticleDetail
结果
Store▶