For AI agents: the complete documentation index is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/llms.txt, the full documentation bundle is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/llms-full.txt, and this page is available as Markdown at https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/scheduler/default-scheduler.md.
  • 简体中文
  • DefaultScheduler

    DefaultScheduler 是异步工厂,返回一个可直接使用的调度器实例。它把模型(默认 FSRS-7)与 dateChrono 以及标准调度策略组合在一起,因此你只需配置它的选项。内部它与自定义 defineScheduler 使用同一套「定义与实例」机制——预设只是把各部分装配起来的便捷方式。

    选项

    从 FSRS-3~6 升级到 FSRS-7 时,省略 weights 以使用 FSRS-7 默认权重,或提供为 FSRS-7 训练的权重。重放历史用于重建卡片状态,不会转换旧版权重。

    FSRS-7 卡片除 stability 和 difficulty 外还包含 stabilityFast。旧版 FSRS-3~6 的记忆状态需要通过 Reschedule 重放复习历史来重建;参数迁移不会迁移卡片状态,不应以 0.8 * stability 推测演化后的快速轨迹。预设为 FSRS-7 启用小数天数;enableShortTerm: false 仅关闭显式学习步骤,不会关闭模型的快速轨迹。

    需要成本自适应保留率时,自行组合定义,用 schedulerCostAdrMiddleware 替换 schedulerDesiredRetentionMiddleware。Cost ADR 不是 DefaultScheduler 选项。

    scheduler.nextInterval(memoryState, desiredRetention, { card, grade, elapsedDays }) 查询已计算的评分后状态所对应的间隔,只执行 handlers.nextInterval,不推进卡片或 chrono;共享间隔策略应放在这个钩子中。

    选项默认用途
    version'FSRS-7'选择 FSRS 模型:'FSRS-3'、'FSRS-4'、'FSRS-4.5'、'FSRS-5', 'FSRS-6' 或 'FSRS-7'。FSRS-7 无法迁移旧版 FSRS-3~6 的权重。
    weights预设权重可选的训练权重;省略时使用所选版本的预设默认值。FSRS-7 需要恰好 34 个 FSRS-7 权重;传入旧版权重会在构造调度器时抛出异常。
    desiredRetention0.9在计算间隔前应用的目标保留率。
    enableShortTermtrue启用学习与再学习步骤。
    learningSteps['1m', '10m']enableShortTerm 开启时应用的学习步骤。
    relearningSteps['10m']enableShortTerm 开启时应用的再学习步骤。
    graduatingInterval1卡片处于 Review 时的最短间隔(天)。最终间隔更短时,卡片保持 Learning/Relearning。配置了步骤时,走完步骤以及 Review 卡片按 Hard、Good、Easy 都至少使用这个间隔。
    allowModelOverrideFSRS-7: true; 其他版本: false模型间隔比当前步骤长时,改用模型间隔。Again 不超过 graduatingInterval;Hard、Good 的间隔达到 graduatingInterval 时提前毕业。
    enableFuzzfalse开启时分散间隔以增加变化。
    maximumInterval36500间隔的天数上限。
    clearStatsOnForgettrueforget 是否清空 reps 与 lapses。

    DefaultScheduler 始终使用 dateChrono,并按中间件页面所述的顺序组合标准策略:目标保留率、模糊间隔、统计、scheduled days、学习步骤、最大间隔、单调间隔。选择 version 只改变模型及其参数,不改变这套策略。

    import { 
    function DefaultScheduler<Version extends DefaultSchedulerVersion = "FSRS-7">(options?: DefaultSchedulerOptions<Version>): Promise<DefaultScheduler<Version>>
    type DefaultScheduler<Version extends DefaultSchedulerVersion = "FSRS-7"> = (Version extends "FSRS-7" ? Omit<SchedulerCore<SchedulerCoreEnv<SchedulerEnvFor<FSRS7DefaultSchedulerModel, Chrono<{
        readonly time: SRSSchema<{
            input: Date;
            output: Date;
        }>;
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly fields: {
            readonly card: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                };
            }>;
            readonly revlog: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                    reviewTime: Date;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                    reviewTime: Date;
                };
            }>;
        };
    }>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>, "definition"> : Omit<...> & {
        ...;
    }) & {
        ...;
    }
    DefaultScheduler
    ,
    type Rating = 0 | 1 | 2 | 3 | 4
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    } from 'ts-fsrs'
    const now = new Date('2026-01-01T00:00:00.000Z') const
    const scheduler: DefaultScheduler<"FSRS-7">
    scheduler
    = await
    DefaultScheduler<"FSRS-7">(options?: DefaultSchedulerOptions<"FSRS-7"> | undefined): Promise<DefaultScheduler<"FSRS-7">>
    DefaultScheduler
    ({
    DefaultSchedulerOptions<"FSRS-7">.version?: "FSRS-7" | undefined

    FSRS model and parameter migration version; defaults to FSRS-7.

    version
    : 'FSRS-7',
    DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.desiredRetention?: number | undefined
    desiredRetention
    : 0.9,
    DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.enableShortTerm?: boolean | undefined

    Enable explicit learning steps. FSRS-7 always retains its intrinsic fast trace.

    enableShortTerm
    : true,
    DefaultSchedulerOptions<"FSRS-7">.learningSteps?: readonly (`${number}d` | `${number}m` | `${number}h`)[] | undefined

    Defaults to ['1m', '10m'].

    learningSteps
    : ['1m', '10m'],
    DefaultSchedulerOptions<"FSRS-7">.relearningSteps?: readonly (`${number}d` | `${number}m` | `${number}h`)[] | undefined

    Defaults to ['10m'].

    relearningSteps
    : ['10m'],
    DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.enableFuzz?: boolean | undefined
    enableFuzz
    : false,
    DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.maximumInterval?: number | undefined
    maximumInterval
    : 36_500,
    }) const
    const card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    =
    const scheduler: DefaultScheduler<"FSRS-7">
    scheduler
    .
    newCard: (options?: ({
        readonly cardId?: string | number | undefined;
    } & {
        readonly now?: Date | undefined;
    }) | undefined) => {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    newCard
    ({ cardId: 'quick-start', now })
    const
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    =
    const scheduler: DefaultScheduler<"FSRS-7">
    scheduler
    .
    review: (input: {
        readonly card: Readonly<Omit<Readonly<{
            stabilityFast: number;
            stability: number;
            difficulty: number;
        } & {
            dueAt: Date;
            lastReviewAt: Date | null;
        } & {
            readonly cardId: string | number;
            readonly reps: number;
            readonly lapses: number;
            readonly scheduledDays: number;
            readonly learningStep?: number | undefined;
        } & SchedulerCoreFields$1<"review" | "new" | "learning">>, keyof SchedulerCoreFields$1<"review" | "new" | "learning">> & SchedulerCoreFields$1<"review" | "new" | "learning">>;
        readonly grade: Grade;
        readonly now?: Date | undefined;
    }) => {
        ...;
    }
    review
    ({ card, grade:
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    .Good, now })
    console.log( JSON.stringify( { state:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .state,
    dueAt:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .dueAt,
    stability:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .stability,
    stabilityFast:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .stabilityFast,
    difficulty:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    }
    card
    .difficulty,
    rating:
    const result: {
        card: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            lapses: number;
            scheduledDays: number;
            learningStep: number;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
        };
        revlog: {
            cardId: string | number;
            stabilityFast: number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            scheduledDays: number;
            learningStep: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "review" | "new" | "learning";
            rating: Grade;
        };
    }
    result
    .
    revlog: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        scheduledDays: number;
        learningStep: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
        rating: Grade;
    }
    revlog
    .rating,
    }, null, 2 ) )

    该工厂是异步的,使用返回的实例前要先 await DefaultScheduler(...)。示例把常用默认值写得很明确:version、desiredRetention、学习与再学习步骤、模糊间隔和 maximumInterval。省略 weights 即用所选 FSRS 版本的预设。

    预设还是自定义定义

    当默认的 FSRS 模型、dateChrono 与标准策略集契合你的产品时,用 DefaultScheduler——这是最快且正确的起点。当需要不同的模型或 chrono、增减策略,或需要为每个用户校验配置时,用 defineScheduler。二者最终都落到同一套调度器实例 API(newCard、review、rollback、preview 与 forget)。定义与实例模型见调度器概览。