如何实现HTML文本区域在程序流程中添加延迟输出?
为啥原来的代码不行?
你写的delay是个卡死主线程的同步循环,浏览器的界面更新和JS代码是同一条线程处理的——线程被这个循环占着的时候,浏览器根本没时间更新文本区域的内容,得等这个2秒的循环跑完,才会一次性把所有内容都刷出来。而console.log直接往控制台打东西,不用等界面渲染,所以能正常分步显示。
解决办法
要让文本区域在4和5之间延迟,得用不卡主线程的异步方法,给浏览器留时间更新界面,下面两种方法都能用:
方法一:用setTimeout拆分任务
把后半段的输出放到setTimeout里,让浏览器先把前半段的内容显示出来,再等2秒执行后半段:
addTxtA = str => document.getElementById("txtA").value+=str+"\n"; window.onload = function() { // 先输出0到4 for (let i = 0; i<5; i++ ) addTxtA(i); // 延迟2秒后输出5到9 setTimeout(() => { for (let i = 5; i<10; i++ ) addTxtA(i); }, 2000); }
方法二:用async/await配合异步延迟
如果以后还要加更多分步延迟,这种方式更灵活,先把delay改成异步函数:
addTxtA = str => document.getElementById("txtA").value+=str+"\n"; // 改成异步的延迟函数,不会卡主线程 function delay(sec){ return new Promise(resolve => setTimeout(resolve, sec * 1000)); } window.onload = async function() { for (let i = 0; i<5; i++ ) addTxtA(i); await delay(2); // 等2秒,这时候浏览器能正常更新界面 for (let i = 5; i<10; i++ ) addTxtA(i); }
简单说原理
异步操作(比如setTimeout或者Promise)会把要延迟的代码放到“待办队列”里,主线程先干完当前的活(比如前半段循环和更新文本区域),闲下来了再去执行队列里的延迟任务,这样就能看到前半段先显示,等2秒再显示后半段的效果。
内容的提问来源于stack exchange,提问作者Poul Christoffersen
相关产品推荐
相关产品推荐

