zh CN Async Interpret - chiba233/yume-dsl-token-walker GitHub Wiki

异步解释 API

解释 API(同步) | 导出一览 | 首页

异步 API 是同步 解释 API 的完整镜像。语义相同、安全保证相同——但 interpret 可以 awaitinterpretChildren 返回 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>"

Demo:在 handler 中 fetch 远程内容

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 awaityield* 消费
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 循环

类型参考

interpretTextAsync

async function* interpretTextAsync<TNode, TEnv>(
  input: string,
  parser: ParserLike,
  ruleset: AsyncInterpretRuleset<TNode, TEnv>,
  env: TEnv,
): AsyncGenerator<TNode>;

interpretTokensAsync

async function* interpretTokensAsync<TNode, TEnv>(
  tokens: TextToken[],
  ruleset: AsyncInterpretRuleset<TNode, TEnv>,
  env: TEnv,
): AsyncGenerator<TNode>;

AsyncInterpretRuleset

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;
}

AsyncInterpretHelpers

interface AsyncInterpretHelpers<TNode, TEnv = unknown> {
  interpretChildren: (value: string | TextToken[]) => AsyncIterable<TNode>;
  flattenText: (value: string | TextToken[]) => string;   // 仍然同步
  env: TEnv;
}

AsyncInterpretResult

type AsyncInterpretResult<TNode> =
  | { type: "nodes"; nodes: Iterable<TNode> | AsyncIterable<TNode> }
  | { type: "text"; text: string }
  | { type: "flatten" }
  | { type: "unhandled" }
  | { type: "drop" };

AsyncUnhandledStrategy

type AsyncUnhandledStrategy<TNode, TEnv = unknown> =
  | "throw"
  | "flatten"
  | "drop"
  | ((
      token: TextToken,
      helpers: AsyncInterpretHelpers<TNode, TEnv>,
    ) => Awaitable<AsyncResolvedResult<TNode>>);

Awaitable

type Awaitable<T> = T | Promise<T>;

用于所有异步 API 签名,让你既可以返回普通值也可以返回 Promise。

⚠️ **GitHub.com Fallback** ⚠️