在jsPsych 7.2中实现条件分支逻辑的问题求助
jsPsych 7.2 条件分支逻辑修复方案
你的代码存在两个核心问题,导致问卷无论第一个选项选什么都会直接结束:
- 提前固定了timeline的执行顺序:你在定义完「是否吃肉」的问题后,直接把「是否吃乳制品」和感谢页面都加入了timeline,这意味着这些环节会强制按顺序执行,完全忽略了你的分支逻辑。
- response索引判断+动态添加trial的逻辑混乱:
jsPsychHtmlButtonResponse的response返回选项的索引(从0开始),你对分支条件的判断不符合选项顺序;同时在on_finish里动态push trial的方式会打乱timeline的执行流程,导致后续环节顺序混乱。
正确实现方案(官方推荐的条件分支方式)
使用jsPsychConditional插件来控制分支流程,这是jsPsych官方设计的条件逻辑控制工具,能避免手动修改timeline带来的问题:
// 定义所有问卷组件 var meatYN = { type: jsPsychHtmlButtonResponse, stimulus: 'Do you eat meat?', choices: ['No', 'Yes'], data: {task: 'meat_check'} }; var rawMeatYN = { type: jsPsychHtmlButtonResponse, stimulus: 'Do you ever eat it raw?', choices: ['No', 'Yes'] }; var dairyYN = { type: jsPsychHtmlButtonResponse, stimulus: 'Do you eat dairy?', choices: ['No', 'Yes'], data: {task: 'dairy_check'} }; var yoghurtLike = { type: jsPsychHtmlButtonResponse, stimulus: 'Do you like yoghurt?', choices: ['No', 'Yes'] }; var thanks = { type: jsPsychInstructions, pages: ['Thanks for your time'] }; // 构建主timeline var timeline = []; // 第一步:询问是否吃肉 timeline.push(meatYN); // 分支1:选择「是」(response=1)→ 询问生肉问题→结束 timeline.push({ type: jsPsychConditional, conditional_function: function(){ // 检查上一个trial的response是否为1(对应Yes选项) return jsPsych.data.get().last(1).values()[0].response === 1; }, timeline: [rawMeatYN, thanks] }); // 分支2:选择「否」(response=0)→ 进入乳制品分支 timeline.push({ type: jsPsychConditional, conditional_function: function(){ return jsPsych.data.get().last(1).values()[0].response === 0; }, timeline: [ dairyYN, // 乳制品分支:选「是」(response=1)→ 询问酸奶问题 { type: jsPsychConditional, conditional_function: function(){ return jsPsych.data.get().last(1).values()[0].response === 1; }, timeline: [yoghurtLike] }, // 无论乳制品选什么,最后都显示感谢 thanks ] }); // 启动问卷 jsPsych.run(timeline);
简化版实现(无需插件)
如果不想使用插件,可以给每个需要条件执行的trial添加conditional属性,通过判断上一个trial的数据来决定是否执行当前trial:
// 定义所有问卷组件 var meatYN = { type: jsPsychHtmlButtonResponse, stimulus: 'Do you eat meat?', choices: ['No', 'Yes'], data: {task: 'meat_check'} }; var rawMeatYN = { type: jsPsychHtmlButtonResponse, stimulus: 'Do you ever eat it raw?', choices: ['No', 'Yes'] }; var dairyYN = { type: jsPsychHtmlButtonResponse, stimulus: 'Do you eat dairy?', choices: ['No', 'Yes'], data: {task: 'dairy_check'} }; var yoghurtLike = { type: jsPsychHtmlButtonResponse, stimulus: 'Do you like yoghurt?', choices: ['No', 'Yes'] }; var thanks = { type: jsPsychInstructions, pages: ['Thanks for your time'] }; var timeline = []; timeline.push(meatYN); // 生肉问题:仅当选择吃肉(response=1)时执行 timeline.push({ ...rawMeatYN, conditional: function(){ return jsPsych.data.get().last(1).values()[0].response === 1; } }); // 乳制品问题:仅当选择不吃肉(response=0)时执行 timeline.push({ ...dairyYN, conditional: function(){ return jsPsych.data.get().last(1).values()[0].response === 0; } }); // 酸奶问题:仅当选择吃乳制品(response=1)时执行 timeline.push({ ...yoghurtLike, conditional: function(){ var lastData = jsPsych.data.get().last(1).values()[0]; return lastData.task === 'dairy_check' && lastData.response === 1; } }); // 最后统一显示感谢页面 timeline.push(thanks); jsPsych.run(timeline);
原代码失败原因说明
你原代码中,在定义完meatYN后直接将dairyYN和thanks加入了timeline,这导致这两个环节会强制执行,完全覆盖了你在on_finish里添加的分支逻辑。用户在选完第一个问题后,会直接进入乳制品问题,然后到感谢页面,此时你动态添加的raw和thanks会在整个流程的最后执行,但用户已经看到感谢页面,误以为问卷结束,所以出现“无论选什么都直接结束”的问题。
内容的提问来源于stack exchange,提问作者Á L
相关产品推荐
相关产品推荐

