astatus

中文文档
0.1.6发布于 2026/11/03MITTypeScriptESM + CJS零依赖

异步状态信号。没有数据,没有获取——只有舞台。

中文使用文档
文档目录20 节
  1. 安装
  2. 使用
  3. API
  4. 创建
  5. 状态阶段
  6. 注入
  7. 读
  8. 观察
  9. 等待
  10. 锁
  11. 重置/销毁
  12. 状态不变
  13. Vue / next
  14. 基本用法
  15. 反应性
  16. 自动清理
  17. next中的wait()
  18. 要求
  19. 笔记
  20. 许可证

astatus

异步状态信号。没有数据,没有获取——只有舞台。

import astatus from "astatus";

const AS = astatus();

AS.pending();
await fetchUser();
await processData(); // however many steps
AS.success(); // you decide when

大多数异步状态库将状态绑定到数据或获取逻辑。 astatus 不喜欢。
这是一个独立的信号,你可以把它注入任何流中,在你选择的任何点。


安装

npm install astatus

使用

import astatus, { STATUS } from "astatus";

const loginAS = astatus({ name: "login" });

// Inject status at the right moment
loginAS.pending();
const data = await fetchUser();
await syncStore(data); // sync or async, as many steps as needed
loginAS.success();

// Read
console.log(loginAS.status); // 'success'
console.log(loginAS.isSuccess); // true

API

所有的例子都使用 const AS = astatus() 除非另有说明。

创建

astatus({ name?, status? })
选项类型默认的描述
namestringnull调试日志名称
statusstring'initial'初始状态

状态阶段

astatus 管理四个内置阶段。这些是库的核心——其他一切都建立在它们之上。

阶段描述
initial尚未启动-默认值
pending在进步
success成功完成
failure失败,带有可选的错误值

您可以通过调用相应的方法在这四个阶段之间移动。这就是整个想法。

AS.pending();
await doSomething();
AS.success();

对于生命周期之外的任何东西, AS.custom('uploading') 接受任何字符串。


注入

AS.initial()
AS.pending()
AS.success()
AS.failure(error?)      // optional error value
AS.custom('uploading')  // any string outside built-in stages

读

AS.status; // 'initial' | 'pending' | 'success' | 'failure' | custom
AS.error; // value passed to failure(), otherwise null
AS.isInitial;
AS.isPending;
AS.isSuccess;
AS.isFailure;
AS.isCustom; // true if current status is not a built-in stage
AS.isLocked;

观察

// All changes
const unsub = AS.subscribe((curr, prev) => {
  console.log(curr.status, prev.status)
})

// Specific status — triggers on both entry and exit
const unwatch = AS.watch('success', (curr, prev) => { ... })
AS.watch(['success', 'failure'], (curr, prev) => { ... })

// Entry only — triggers once on transition into the status
const unwatch = AS.when('success', (curr, prev) => { ... })

// Cleanup
unsub()
unwatch()

等待

// As a timing gate — wait for the right moment, then continue
await AS.wait();
await AS.wait("success");

// As a result — inspect what happened
const { status, error, timeout, immediate } = await AS.wait();
const result = await AS.wait(["success", "failure"], 15); // timeout in seconds
场描述
status解析时的状态(快照)
error解析时错误
timeouttrue 如果超时
immediatetrue 如果已经处于目标状态
destroyedtrue 如果实例在解析之前被销毁

如果 destroy() 被称为while a wait() 是悬而未决的,它立即解决 destroyed: true.


锁

AS.lock(); // block all status changes
AS.unlock(); // unblock

重置/销毁

AS.reset(); // back to initial, clears error and lock
AS.destroy(); // resolves all pending wait()s, clears all listeners, blocks all further changes

状态不变

import { STATUS } from "astatus";

STATUS.INITIAL; // 'initial'
STATUS.PENDING; // 'pending'
STATUS.SUCCESS; // 'success'
STATUS.FAILURE; // 'failure'

Vue / next

astatus 包括一个Vue可组合的开箱即用。不需要额外的安装。

import { useAstatus } from "astatus/vue";

基本用法

<script setup>
import { useAstatus } from "astatus/vue";

const loginAS = useAstatus({ name: "login" });

const handleLogin = async () => {
    loginAS.pending();
    try {
        await fetchUser();
        loginAS.success();
    } catch (e) {
        loginAS.failure(e);
    }
};
</script>

<template>
    <button :disabled="loginAS.isPending" @click="handleLogin">
        {{ loginAS.isPending ? "Loading..." : "Login" }}
    </button>
    <p v-if="loginAS.isFailure">{{ loginAS.error }}</p>
</template>

反应性

status 和 error 是只读引用。 isInitial, isPending, isSuccess, isFailure, isCustom 都是计算值——都是响应式的,可以安全地在模板中使用。

ref在模板中会自动展开,所以 .value 这里不需要。

const AS = useAstatus();

// script: use .value
watch(AS.isPending, (val) => {
    console.log("pending:", val);
});

// template: no .value needed
// <p v-if="AS.isPending">...</p>

注意: 破坏破坏了反应性。总是直接使用返回的对象。

// ✅
const loginAS = useAstatus();
// loginAS.isPending in template

// ❌ reactivity lost
const { isPending } = useAstatus();

自动清理

可组合的自动调用 destroy() 通过卸载组件 onUnmounted. 在大多数情况下不需要手动清理。

如果你使用 useAstatus 在组件外部(例如在一个Pinia store中),自动清理不适用- call destroy() 手动完成时。

// Pinia store
const AS = useAstatus();

// when no longer needed
AS.destroy();

要使实例在其组件之后保持存活(例如,在路由更改时缓存),pass autoDestroy: false. 你拥有它的生命周期-呼叫 destroy() 如果它应该结束的话,你自己。在组件内部创建时需要Vue 3.5+,因为早期版本在卸载时停止组件的计算。

const cache = {};
const boardAS = (cache.board ??= useAstatus({ name: "board", autoDestroy: false }));

next中的wait()

wait() 使用 setTimeout 在内部。在next中,避免在SSR期间调用它-在内部使用它 onMounted 或者用 import.meta.client.

// ✅ safe
onMounted(async () => {
    await AS.wait();
});

// ✅ safe
if (import.meta.client) {
    await AS.wait();
}

要求

  • Vue >= 3.3.0

笔记

  • subscribe / watch / when 返回一个退订函数——调用它来清理。
  • destroy() 解决所有悬而未决的问题 wait() 立即调用,然后清除所有侦听器。
  • 侦听器错误被捕获并单独记录,而不会破坏其他侦听器。

许可证

麻省理工学院


自述部分编辑与人工智能的帮助。

版本与发布记录

astatus 共发布 7 个版本,首次发布于 2026/03/16;过去 12 个月发布了 7 个版本。

版本发布日期距今
0.1.6latest2026/11/03今天
0.1.52026/03/257 个月前
0.1.42026/03/177 个月前
0.1.32026/03/177 个月前
0.1.22026/03/177 个月前
0.1.12026/03/177 个月前

其他发布通道:beta → 0.1.0。

关于 astatus 的常见问题

astatus 是什么?

异步状态信号。没有数据,没有获取——只有舞台。

如何安装 astatus?

在项目目录运行 npm install astatus,或使用 pnpm add / yarn add / bun add。

astatus 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

astatus 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

astatus 可以商用吗?

astatus 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

astatus 还在维护吗?

最新版本 0.1.6 发布于 2026/11/03(今天);至今共发布 7 个版本,其中过去 12 个月发布了 7 个;首次发布于 2026/03/16。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。