本文详解 JsPsych 中实现“达到指定正确次数后自动终止循环”的正确方法,重点解决因变量作用域错误(如在 on_finish 内重复声明计数器)导致的无限循环问题,并提供可直接运行的结构化代码示例。
本文详解 jspsych 中实现“达到指定正确次数后自动终止循环”的正确方法,重点解决因变量作用域错误(如在 `on_finish` 内重复声明计数器)导致的无限循环问题,并提供可直接运行的结构化代码示例。
在 JsPsych 中,通过 loop_function 控制试验循环是常见需求,但若未正确管理状态变量(尤其是正确计数器),极易陷入无限循环——典型表现是任务永不结束、控制台无报错、loop_function 持续返回 true。根本原因往往在于计数变量的作用域与生命周期不匹配:例如将 acc = 0 或 correctCount 声明在 on_finish 回调内部,导致每次试验结束时该变量被重新初始化为 0,永远无法累积到目标阈值。
✅ 正确实践:全局计数器 + 精确的数据访问
以下是一个健壮、可复用的数学测验示例,目标为连续获得 3 次正确回答即退出循环(便于快速验证,可按需改为 10):
<title>Math Quiz with Accuracy Criterion</title><script src="jspsych/dist/jspsych.js"></script><script src="jspsych/dist/plugin-survey-text.js"></script><link href="jspsych/dist/jspsych.css" rel="stylesheet" type="text/css"><script>
const jsPsych = initJsPsych();
// ✅ 步骤1:在全局作用域定义计数器(关键!)
let correctCount = 0;
const ACCURACY_TARGET = 3;
// ✅ 步骤2:预定义题目库(结构清晰,支持动态渲染)
const mathQuestions = [
{ math: '2 + 2 = ?', correct: '4' },
{ math: '3 × 7 = ?', correct: '21' },
{ math: 'How many days in a week?', correct: '7' }
];
// ✅ 步骤3:定义单次试验(使用 timeline_variables 实现题目轮换)
const testTrial = {
type: jsPsychSurveyText,
questions: [
{
prompt: jsPsych.timelineVariable('math'),
name: 'resp',
required: true
}
],
post_trial_gap: 500,
on_finish: function(data) {
// ✅ 步骤4:从 data.response.resp 获取用户输入(注意嵌套结构)
const userResponse = data.response.resp?.trim();
const expectedAnswer = jsPsych.timelineVariable('correct');
// ✅ 严格比对(忽略大小写和空格)
const isCorrect = userResponse &&
userResponse.toLowerCase() === expectedAnswer.toLowerCase();
// ✅ 更新全局计数器
if (isCorrect) {
correctCount++;
console.log(`✅ Correct! Count = ${correctCount}/${ACCURACY_TARGET}`);
} else {
console.log(`❌ Incorrect. Current count = ${correctCount}/${ACCURACY_TARGET}`);
}
// 将结果存入 data 便于调试和导出
data.correct = isCorrect;
data.correctCount = correctCount;
}
};
// ✅ 步骤5:配置循环节点 —— loop_function 必须能访问 correctCount
const mathLoop = {
timeline: [testTrial],
timeline_variables: mathQuestions,
sample: { type: 'with-replacement' }, // 随机抽样,允许重复
loop_function: function(data) {
// ✅ 关键逻辑:检查是否达成目标
if (correctCount >= ACCURACY_TARGET) {
console.log('? Accuracy criterion met. Ending loop.');
return false; // 终止循环
} else {
return true; // 继续下一轮
}
}
};
// 启动实验
jsPsych.run([mathLoop]);
</script>
⚠️ 常见错误与规避要点
-
❌ 错误:在 on_finish 内声明计数器
on_finish: function(data) { let correctCount = 0; // ❌ 每次都重置!永远无法累积 if (data.correct) correctCount++; // 无效 }→ ✅ 修复:计数器必须声明在 loop_function 和 on_finish 共同可见的外层作用域(如全局或闭包内)。
OpenGemini Next.js Bestpractice Builder下载使用固定的 Next.js/Tailwind/Prisma 技术栈构建并记录独立 SaaS 项目,仅将 FastAPI 用于 Python 工作负载,并遵循严格的架构规范。
❌ 错误:错误访问响应数据
data.response 在 survey-text 插件中是对象(如 {resp: "4"}),而非字符串。应使用 data.response.resp。❌ 错误:loop_function 中未正确处理 data 参数
loop_function 的 data 参数是当前循环批次所有 trial 的数据数组,但此处我们依赖的是全局计数器,因此无需解析该参数(除非需做复杂统计)。
? 进阶建议
- 若需“连续 N 次正确”(而非累计),可维护一个数组记录最近 N 次结果,用 every() 判断;
- 对于生产环境,建议添加超时保护(如最大尝试次数 maxTrials: 50),防止因逻辑漏洞导致死循环;
- 使用 jsPsych.data.get().filter({trial_type: 'survey-text'}).select('correct').values 可在实验后校验计数逻辑。
通过严格分离状态管理(全局计数器)与试验逻辑(on_finish 数据处理),即可稳定实现基于准确率的自适应循环,这是构建自适应认知任务、训练范式或个性化测验的核心基础。










