zh CN Async Interpret - chiba233/yume-dsl-token-walker GitHub Wiki
解释 API(同步) | 导出一览 | 首页
异步 API 是同步 解释 API 的完整镜像。语义相同、安全保证相同——但 interpret 可以 await,interpretChildren 返回 AsyncIterable。
什么时候用异步版:
- handler 里需要
fetch远程内容 - handler 里查数据库
- handler 里调异步渲染器(如 Shiki
codeToHtml)
如果你的 handler 都不需要 async,用同步 API 就好——更简单,零异步开销。
import { createParser, createSimpleInlineHandlers } from "yume-dsl-rich-text";
import { interpretTextAsync, collectNodesAsync } from "yume-dsl-token-walker";
const parser = createParser({
handlers: createSimpleInlineHandlers(["bold"]),
});
const html = (
await collectNodesAsync(
interpretTextAsync("Hello $$bold(world)$$", parser, {
createText: (text) => text,
interpret: async (token, helpers) => {
if (token.type === "bold") {
return {
type: "nodes",
nodes: (async function* () {
yield "<b>";
yield* helpers.interpretChildren(token.value);
yield "</b>";
})(),
};
}
return { type: "unhandled" };
},
}, undefined),
)
).join("");
// → "Hello <b>world</b>"import type { AsyncInterpretRuleset } from "yume-dsl-token-walker";
import { interpretTokensAsync, collectNodesAsync } from "yume-dsl-token-walker";
const ruleset: AsyncInterpretRuleset<string, void> = {
createText: (text) => text,
interpret: async (token, helpers) => {
if (token.type === "embed") {
const url = typeof token.url === "string" ? token.url : "";
const response = await fetch(url);
const html = await response.text();
return { type: "text", text: `<div class="embed">${html}</div>` };
}
if (token.type === "bold") {
return {
type: "nodes",
nodes: (async function* () {
yield "<b>";
yield* helpers.interpretChildren(token.value);
yield "</b>";
})(),
};
}
return { type: "unhandled" };
},
onUnhandled: "flatten",
};
const nodes = await collectNodesAsync(
interpretTokensAsync(tokens, ruleset, undefined),
);| 方面 | 同步 | 异步 |
|---|---|---|
interpret 返回 |
InterpretResult<TNode> |
Awaitable<AsyncInterpretResult<TNode>>——可以返回 Promise |
interpretChildren 返回 |
Iterable<TNode> |
AsyncIterable<TNode>——用 for await 或 yield* 消费 |
result 中的 nodes
|
Iterable<TNode> |
Iterable<TNode> | AsyncIterable<TNode>——普通数组和 async generator 都行 |
createText |
同步 | 仍然同步——文本包装是纯操作 |
onUnhandled 函数 |
返回 ResolvedResult
|
返回 Awaitable<AsyncResolvedResult>
|
| 错误处理、递归检测 | 相同 | 相同 |
| 函数 | 说明 |
|---|---|
fromAsyncHandlerMap(handlers) |
从 Record<type, asyncHandler> 构建异步 interpret 函数。未匹配的 token 返回 { type: "unhandled" }
|
wrapAsyncHandlers(handlers, wrap) |
给每个异步 handler 套统一包装。wrap 回调收到的是 await 后的结果 |
collectNodesAsync(iterable) |
把 AsyncIterable<TNode> 收集为数组。等价于 for await 循环 |
async function* interpretTextAsync<TNode, TEnv>(
input: string,
parser: ParserLike,
ruleset: AsyncInterpretRuleset<TNode, TEnv>,
env: TEnv,
): AsyncGenerator<TNode>;async function* interpretTokensAsync<TNode, TEnv>(
tokens: TextToken[],
ruleset: AsyncInterpretRuleset<TNode, TEnv>,
env: TEnv,
): AsyncGenerator<TNode>;interface AsyncInterpretRuleset<TNode, TEnv = unknown> {
createText: (text: string) => TNode; // 始终同步
interpret: (
token: TextToken,
helpers: AsyncInterpretHelpers<TNode, TEnv>,
) => Awaitable<AsyncInterpretResult<TNode>>;
onUnhandled?: AsyncUnhandledStrategy<TNode, TEnv>; // 默认 "flatten"
onError?: (context: {
error: Error;
phase: "interpret" | "flatten" | "traversal" | "internal";
token?: TextToken;
position?: SourceSpan;
env: TEnv;
}) => void;
}interface AsyncInterpretHelpers<TNode, TEnv = unknown> {
interpretChildren: (value: string | TextToken[]) => AsyncIterable<TNode>;
flattenText: (value: string | TextToken[]) => string; // 仍然同步
env: TEnv;
}type AsyncInterpretResult<TNode> =
| { type: "nodes"; nodes: Iterable<TNode> | AsyncIterable<TNode> }
| { type: "text"; text: string }
| { type: "flatten" }
| { type: "unhandled" }
| { type: "drop" };type AsyncUnhandledStrategy<TNode, TEnv = unknown> =
| "throw"
| "flatten"
| "drop"
| ((
token: TextToken,
helpers: AsyncInterpretHelpers<TNode, TEnv>,
) => Awaitable<AsyncResolvedResult<TNode>>);type Awaitable<T> = T | Promise<T>;用于所有异步 API 签名,让你既可以返回普通值也可以返回 Promise。