将JsPsych实验数据从HTML导出为CSV失败求助
问题:jsPsych实验结束后弹出数据网页而非下载CSV文件
我一直在尝试把通过脚本运行的HTML实验数据保存为CSV文件到本地,但实验结束后总是弹出显示所有数据的新网页,而非下载CSV文件。我怀疑问题出在var jsPsych和var today这两个变量上,请问哪里操作有误?
<!DOCTYPE html> <html> <head> <title>My experiment</title> <script src="https://unpkg.com/jspsych@7.2.3"></script> <script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.1"></script> <script src="https://unpkg.com/@jspsych/plugin-survey-multi-choice@1.1.1"></script> <link href="https://unpkg.com/jspsych@7.2.3/css/jspsych.css" rel="stylesheet" type="text/css" /> </head> <body></body> <script> /* initialize jsPsych */ /*var jsPsych = initJsPsych();*/ var jsPsych = initJsPsych({ timeline: timeline, show_progress_bar: true, override_safe_mode: true, on_finish: function() { jsPsych.data .get() .localSave( 'csv', 'ekstra.html' ); }, }); var today = new Date(); jsPsych.data.addProperties({ date: ("0" + today.getDate()).slice(-2) + '-' + ("0" + (today.getMonth() + 1)).slice(-2) + '-' + today.getFullYear(), time: today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(), }); /* create timeline */ var timeline = []; // generate a random subject ID with 15 characters var subject_id = jsPsych.randomization.randomID(6); // this adds a property called 'subject' to every trial jsPsych.data.addProperties({ subject: subject_id, }); var time_limit = 10000; var start_time2; var end_test_timer; var trial_count = 0; var n_trials = 7; var counter2 = 1; var sproglyde = { type: jsPsychSurveyMultiChoice, data: { sproglyde_test: 'Sproglyde' }, questions: [ { prompt: "<p>Vælg det 'ord' der lyder som et rigtigt dansk ord.</p><p>Vælg ordet (gæt evt.):</p>", name: 'Sproglyd1', options: ['sbese', 'sbuse', 'sbise', 'befse'], required: true }, { prompt: "Vælg ordet (gæt evt.):", name: 'Sproglyd2', options: ['sigam', 'sigar', 'sigur', 'sigat'], required: true }, { prompt: "Vælg ordet (gæt evt.):", name: 'Sproglyd3', options: ['nåmmer', 'nymmer', 'måmmer', 'fåmmer'], required: true } ], on_load: function() { trial_count++; // we need to set up the timer to end the current timeline after a certain duration, but only on the first trial if (trial_count > 0) { start_time2 = performance.now(); var end_test_timer = setTimeout(function() { // this stuff is just for testing var end_time = performance.now(); var elapsed_time = end_time - start_time2; console.log("elapsed time: ", elapsed_time); // this function ends the current trial jsPsych.finishTrial({status: "ended early"}); }, time_limit); } }, on_finish: function() { counter2++; // we also need to cancel the setTimeout timer if the person gets all the way through the timeline before // time_limit is reached, otherwise endCurrentTimeline will fire during the next timeline - not good!! if (trial_count == n_trials) { clearTimeout(end_test_timer); } } }; timeline.push(sproglyde); var Ordforråds = { type: jsPsychSurveyMultiChoice, data: { ordforraad_test: 'ordforraad' }, questions: [ { prompt: "<p>Vælg det ord som findes på dansk. Tænk ikke for længe. Du er velkommen til at gætte, hvis du ikke kender svaret</p>", name: 'Ordforråd1', options: ['gis', 'gim', 'git'], required: true }, { prompt: "Vælg ordet (gæt evt.):", name: 'Ordforråd2', options: ['trokæ', 'troklæ', 'tropæ'], required: true }, { prompt: "Vælg ordet (gæt evt.):", name: 'Ordforråd3', options: ['tights', 'tigts', 'kights'], required: true } ], }; timeline.push(Ordforråds); /* run the experiment */ jsPsych.run(timeline); </script> </html>
问题分析与修复方案
1. 核心问题:CSV文件名后缀错误
你在localSave方法里指定的文件名是'ekstra.html',浏览器会把这个文件识别为HTML类型,因此直接打开而非触发下载。必须把后缀改成.csv:
jsPsych.data .get() .localSave( 'csv', 'ekstra.csv' // 从.html改为.csv );
2. 初始化jsPsych时的时间线变量未定义
调用initJsPsych时传入了timeline: timeline,但此时timeline还未声明(后续才定义var timeline = []),会导致初始化错误。应移除该参数,因为后续已通过jsPsych.run(timeline)指定运行的时间线:
var jsPsych = initJsPsych({ // 移除 timeline: timeline 这一行 show_progress_bar: true, override_safe_mode: true, on_finish: function() { jsPsych.data .get() .localSave('csv', 'ekstra.csv'); }, });
3. 定时器变量作用域问题
在sproglyde的on_load函数里,用var end_test_timer重新声明变量,导致on_finish里的clearTimeout无法访问正确的定时器ID。需去掉on_load里的var,直接使用全局声明的end_test_timer:
on_load: function() { trial_count++; if (trial_count > 0) { start_time2 = performance.now(); // 去掉var,直接赋值给全局变量 end_test_timer = setTimeout(function() { var end_time = performance.now(); var elapsed_time = end_time - start_time2; console.log("elapsed time: ", elapsed_time); jsPsych.finishTrial({status: "ended early"}); }, time_limit); } },
4. 额外优化:日期时间格式的引号问题
代码中"0"使用了中文引号,虽浏览器可能兼容,但建议改为英文双引号,避免潜在语法问题:
date: ("0" + today.getDate()).slice(-2) + '-' + ("0" + (today.getMonth() + 1)).slice(-2) + '-' + today.getFullYear(), time: today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(),
内容的提问来源于stack exchange,提问作者carolinehommel
相关产品推荐
相关产品推荐

