使用setTimeout无法实现逐行输出?

arr里面有10组数据,让它每过2秒就输出一条,直到输出完成,我是用了setTimeout间隔了2秒输出
,但是没有效果,最终还是一次性输出所有。

arr.map((item)=>{
    setTimeout(function(){
        $('id').innerHTML(item.id)
    ,2000);
})
阅读 2.4k
8 个回答

你这个相当于同时执行了这样执行了arr.length

setTimeout(function(){
    $('id').innerHTML(item.id)
,2000);
setTimeout(function(){
    $('id').innerHTML(item.id)
,2000);
setTimeout(function(){
    $('id').innerHTML(item.id)
,2000);
// 继续执行

你需要的是等上一次执行完了,下一次才开始执行,这个用promise比较合适

function promiseSetTimeout () {
    return new Promise((res, rej) => {
        setTimeout(() => {
            console.log('trigger')
            res()
        }, 2000)
    })
}
async function run () {
    await promiseSetTimeout()
}
run() // 你会发现过2s打印一次trigger
[1,2,3,4,5,6,7,8,9,10].map((item,index)=>{
    setTimeout(function(){
        console.log(item)
    },(index+1)*2000);
})
arr.map((item)=>{
    setTimeout(function(){
        $('id').innerHTML(item.id)
    ,2000);
})

是不是应该设置2000,4000,...这样才能大致隔2秒输出一条

建议先处理数据再用setInterval打印数据,结束后再清除定时器

点击这个链接
https://www.w3school.com.cn/tiy/t.asp?f=eg_js_myfirstjs
复制以下代码,然后点“运行代码”查看效果。

<!DOCTYPE html>
<html>
<body>
<span id="id"></span>

<script>
var arr=[1,2,3,4,5,6,7,8,9,10];
var t=setInterval(print,2000);
var i=0;
function print(){

     document.getElementById('id').innerHTML+=arr[i]+"<br>";
     i++;
     if(i==arr.length){
     clearTimeout(t);
     }
}
</script>
</body>
</html>

image.png

包装一下

const interval = (items, callback, ms) => {
    let index = 0, len = items.length;
    const fn = () => {
        if(index < len) {
            callback(items[index], index);
            setTimeout(fn, ms);
            index++;            
        }
    };
    fn();
}

interval([1,2,3], (val, index) => console.log(val), 2000);

//interval(arr, (item) => $('id').innerHTML(item.id), 2000);

代码中的时间设置的不正确,应该为:

arr.map((item, index)=>{
    setTimeout(function(){
        $('id').innerHTML(item.id)
    , (index+1)* 2000);
})
本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。
const sleep = time => new Promise(resolve => setTimeout(resolve, time))

async function main() {
    for (const item of arr) {
        await sleep(2000)
        $('id').innerHTML(item.id)
    }
}
main()

setTimeout方法并不会阻塞代码的执行,它只是在指定的时间后将回调函数添加到事件队列中。因此,你的代码会立即执行所有的setTimeout方法,然后等待2秒后才会依次执行回调函数。这就导致了所有的输出都在同一时间完成。

要解决这个问题,你可以使用async/await和for循环来实现。具体来说,你可以将setTimeout方法包装在一个Promise对象中,并使用await关键字等待2秒后再执行下一次循环。代码如下:

async function outputItems(arr) {
for (const item of arr) {

await new Promise(resolve => {
  setTimeout(() => {
    $('id').innerHTML(item.id);
    resolve();
  }, 2000);
});

}
}

outputItems(arr);

请注意,你需要将代码放在一个异步函数中,并将arr作为参数传递给该函数。此外,你需要将$('id')替换为实际的DOM元素。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏