JS读取文件逐行输出添加1秒行间延迟功能失效如何解决
问题原因
你之前的写法无法生效主要有两个核心原因:
- 定时器是异步API,for循环是同步执行逻辑,把
setTimeout放在for循环外的话,仅会触发1次延迟,延迟结束后for循环会瞬间跑完所有打印逻辑,不会产生逐行间隔的效果 - 如果把
setTimeout放在for循环内、延迟固定写1000ms的话,所有定时器会被同步一次性注册完成,1秒后所有回调会同时触发,再加上你用var声明的line变量存在变量提升问题,所有回调最终拿到的都是循环结束后的line值,还会出现打印内容错误的问题
解决方案
下面提供两种可直接使用的实现方案:
方案1:递归触发定时器(更推荐)
该方案在上一行打印完成后才开始计算下一行的1秒间隔,就算有额外逻辑耗时也能保证两行的打印间隔严格为1秒,不会出现时间偏移,也不会有变量作用域问题:
document.getElementById('file').onchange = function() { var file = this.files[0]; var reader = new FileReader(); reader.onload = function(progressEvent) { var fileContentArray = this.result.split(/\r\n|\n/); // 可选:移除末尾空行 if(fileContentArray[fileContentArray.length - 1] === '') fileContentArray.pop() let currentLine = 0 function printNextLine() { // 所有行打印完成就终止 if(currentLine >= fileContentArray.length) return console.log(currentLine + " --> " + fileContentArray[currentLine]) currentLine++ // 1秒后打印下一行 setTimeout(printNextLine, 1000) } // 启动首次打印 printNextLine() }; reader.readAsText(file); };
方案2:块级作用域+递增延迟
使用let声明循环变量生成独立块级作用域,给每一行的定时器设置递增的延迟时间,实现依次触发:
document.getElementById('file').onchange = function() { var file = this.files[0]; var reader = new FileReader(); reader.onload = function(progressEvent) { var fileContentArray = this.result.split(/\r\n|\n/); // 用let声明循环变量,每次循环生成独立作用域 for (let line = 0; line < fileContentArray.length; line++) { // 第line行延迟line*1000毫秒触发 setTimeout(function() { console.log(line + " --> " + fileContentArray[line]); }, line * 1000) } }; reader.readAsText(file); };
内容的提问来源于stack exchange,提问作者user16974637
相关产品推荐
相关产品推荐

