同步构造异步属性模式Skill sync-construction-async-property-ui-render-gate-pattern

一种软件设计模式,用于在需要异步初始化的客户端中实现同步构造和异步属性,使模块可导出并在UI组件中同步使用,避免顶级await问题。适用于前端开发,如SvelteKit应用,通过UI渲染门确保异步工作完成后才渲染UI。关键词:同步构造、异步属性、UI渲染门、前端开发、模块导出、SvelteKit、异步初始化。

前端开发 0 次安装 0 次浏览 更新于 3/20/2026

名称: 同步构造异步属性UI渲染门模式 描述: 同步构造与异步属性模式。用于创建需要异步初始化但必须可模块导出并在UI组件中同步使用的客户端。 元数据: 作者: epicenter 版本: ‘1.0’

同步构造,异步属性

客户端的初始化是同步的。异步工作存储为一个属性,您可以await,同时传递引用。

何时应用此模式

在以下情况使用:

  • 需要异步客户端初始化(IndexedDB、服务器连接、文件系统)
  • 模块导出需要在没有await的情况下可导入
  • UI组件希望同步访问客户端
  • SvelteKit应用,您希望在准备就绪时门控渲染

信号表明您正在处理异步构造问题:

  • 到处使用await getX()模式
  • 捆绑器抱怨顶级await
  • 包装单例访问的getter函数
  • 组件无法直接导入客户端

问题

异步构造函数无法导出:

// 这不可行
export const client = await createClient(); // 顶级await破坏捆绑器

因此您最终会使用getter模式:

let client: Client | null = null;

export async function getClient() {
	if (!client) {
		client = await createClient();
	}
	return client;
}

// 每个使用者必须await
const client = await getClient();

每个调用点都需要await。您传递的是承诺而不是对象。

模式

使构造同步。将异步工作附加到对象:

// client.ts
export const client = createClient();

// 同步访问立即工作
client.save(data);
client.load(id);

// 当需要时await异步工作
await client.whenSynced;

构造立即返回。异步初始化(从磁盘加载、连接到服务器)在后台发生,并通过whenSynced跟踪。

UI渲染门

在Svelte中,在根组件处await一次:

<!-- +layout.svelte -->
<script>
	import { client } from '$lib/client';
</script>

{#await client.whenSynced}
	<LoadingSpinner />
{:then}
	{@render children?.()}
{/await}

门控保证:在任何子组件的脚本运行之前,异步工作已完成。子组件使用同步访问而无需检查准备状态。

实现

withCapabilities()流畅构建器将异步工作附加到同步构造的对象:

function createClient() {
	const state = initializeSyncState();

	return {
		save(data) {
			/* 同步方法 */
		},
		load(id) {
			/* 同步方法 */
		},

		withCapabilities({ persistence }) {
			const whenSynced = persistence(state);
			return Object.assign(this, { whenSynced });
		},
	};
}

// 用法
export const client = createClient().withCapabilities({
	persistence: (state) => loadFromIndexedDB(state),
});

之前与之后

方面 异步构造 同步 + whenSynced
模块导出 无法直接导出 导出对象
消费者代码 到处await getX() 直接导入,同步使用
UI集成 尴尬的承诺处理 单一{#await}门控
类型签名 Promise<X> X.whenSynced

真实世界示例: y-indexeddb

Yjs生态系统普遍使用此模式:

const provider = new IndexeddbPersistence('my-db', doc);
// 构造函数立即返回

provider.on('update', handleUpdate); // 同步访问工作

await provider.whenSynced; // 当需要时等待

他们从不阻塞构造。异步工作总是延迟到您可以await的属性。

相关模式

参考文献