
本文详解 jsPsych 中使用 conditional_function 实现条件化事件插入的方法,解决“在时间线运行中根据按钮选择动态添加中间试次”的核心问题,避免 timeline 静态定义导致的逻辑僵化。
本文详解 jspsych 中使用 `conditional_function` 实现条件化事件插入的方法,解决“在时间线运行中根据按钮选择动态添加中间试次”的核心问题,避免 timeline 静态定义导致的逻辑僵化。
在 jsPsych 实验开发中,一个常见但易被误解的需求是:根据被试在前一试次中的实时反应,决定是否插入后续特定事件(如提示信息、补救试次或分支流程)。初学者常尝试在 on_finish 回调中直接修改 timeline 数组(如 timeline.push() 或 splice()),或调用 jsPsych.addNodeToEndOfTimeline() —— 这些方法均会失败,因为 jsPsych 的主 timeline 在 jsPsych.run() 执行时已被解析并固化为执行计划,运行时无法安全地“中途改道”。
✅ 正确解法是利用 jsPsych 内置的 条件节点(Conditional Node) 机制:将待条件化插入的事件封装为一个独立的 timeline 节点,并为其配置 conditional_function 属性。该函数在每个时间点被自动调用,返回 true 则执行该节点,返回 false 则跳过,从而实现“逻辑上动态、结构上静态”的优雅分支。
以下是一个完整、可运行的实践示例,实现题目要求的三态流程:
- 首屏显示 A/B/C 按钮;
- 若选 A → 直接跳至结束页;
- 若选 B 或 C → 插入一条提示信息页(Message),再进入结束页。
// 定义基础试次
const ChoiceTrial = {
type: jsPsychHtmlButtonResponse,
stimulus: 'Choose A to end, or B or C to see a message',
choices: jsPsych.randomization.sampleWithoutReplacement(['A', 'B', 'C'], 3)
};
const Message = {
type: jsPsychHtmlKeyboardResponse,
stimulus: 'Congrats, It worked! Press Space to Continue',
choices: [' ']
};
const Conclusion = {
type: jsPsychHtmlKeyboardResponse,
stimulus: 'The experiment Ended! Press Space to Continue',
choices: [' ']
};
// ✅ 关键:定义条件节点
const ifNode = {
timeline: [Message],
conditional_function: function() {
// 获取最近一次试次的数据(注意:需确保 ChoiceTrial 已完成)
const lastData = jsPsych.data.get().last(1).values()[0];
// 获取 A 在原始 choices 数组中的索引(因 choices 已随机化)
const choiceArray = ['A', 'B', 'C']; // 注意:此处应与 ChoiceTrial 中实际使用的 choices 一致
const aIndex = choiceArray.indexOf('A');
// 若被试响应等于 A 的索引,则跳过 Message;否则执行
return lastData.response !== aIndex;
}
};
// 构建最终 timeline:顺序执行,条件节点自动生效
jsPsych.run([ChoiceTrial, ifNode, Conclusion]);? 关键注意事项:
- conditional_function 中访问数据必须使用 jsPsych.data.get().last(1),而非 jsPsych.data.getLastTrialData() —— 后者在某些版本中可能返回未及时刷新的数据;
- response 值是按钮在 choices 数组中的索引号(0-based),不是按钮文本本身。因此判断逻辑必须基于索引(如 choice.indexOf('A')),而非字符串比较;
- 条件节点必须置于其依赖的前驱试次之后(如 ifNode 紧跟 ChoiceTrial),且不能放在 on_finish 内部调用;
- 若需多层嵌套条件(如二级分支),可叠加多个 conditional_function 节点,或使用更复杂的返回逻辑(如返回 data.response === 1 && data.rt > 2000);
- 所有试次类型(包括条件节点内的试次)仍受全局 preload 和 default_ 参数影响,建议统一配置。
通过 conditional_function,你无需操作 timeline 内部结构,即可实现高度灵活的实验流程控制——这正是 jsPsych “声明式流程 + 函数式条件”设计哲学的精妙体现。掌握此模式,可轻松构建问卷跳转、错误反馈、自适应范式等复杂实验逻辑。


















