您的位置:

从多个方面深入了解JS暂停几秒再执行

一、使用setTimeout实现JS暂停几秒再执行

JS是一门单线程语言,在执行一个任务时,会阻塞之后的任务,这就导致了一些场景下需要暂停JS执行,等待一段时间再继续执行的情况。setTimeout函数就是一种解决方案。

setTimeout(function(){
    //需要暂停执行的代码
}, 1000);

setTimeout的第一个参数是一个匿名函数,在其中编写需要暂停执行的代码。第二个参数表示需要暂停的时间,单位是毫秒。上述代码表示暂停1秒后执行代码。

需要注意的是,setTimeout的精度不一定很高。因为JS是单线程运行的,当时间到期后,JS需要获得资源才能真正地执行代码。如果此时正在执行其他任务,setTimeout就需要等待其他任务执行完毕后才能执行。这就导致在执行繁忙任务时,setTimeout的实际执行时间可能会比设置的时间晚几十甚至几百毫秒。

二、使用Promise实现JS暂停几秒再执行

Promise是ES6中新引入的特性,用于异步编程。通过Promise对象,我们可以更加方便地实现JS暂停几秒再执行的需求。我们可以使用Promise的setTimeout方法:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
  console.log('Hello');
  await sleep(1000);
  console.log('World');
}
main(); //打印Hello后,暂停1秒后再打印World

上述代码中,sleep函数返回一个Promise对象,resolve函数会在过了指定的毫秒数后被调用。main函数通过async关键字声明,await后面跟着一个Promise对象,表示要等待Promise对象的完成,才能继续执行下面的代码。

三、使用Generator函数实现JS暂停几秒再执行

Generator是ES6中的另一个新特性,可以使用它实现JS暂停几秒再执行的需求。

function* sleep(ms) {
  yield new Promise(resolve => setTimeout(resolve, ms));
}
function* main() {
  console.log('Hello');
  yield* sleep(1000);
  console.log('World');
}
for(let s of main()){s}

上述代码中,Generator函数sleep返回一个Promise对象,通过使用yield关键字,表示函数暂停并返回一个Promise对象。main函数通过yield*关键字,暂停执行,等待sleep函数执行完毕后再继续执行下面的代码。

需要注意的是,Generator函数的执行需要使用遍历器实现。因此在最后使用了一个for...of循环来遍历main函数,实现暂停几秒后再执行的效果。

四、注意JS暂停几秒再执行会阻塞UI线程

在JS暂停几秒再执行时,会阻塞UI线程,导致网页卡顿。例如:

console.log('Start');
setTimeout(function(){
    for(let i=0; i<1000000000; i++){}
    console.log('End');
}, 5000)

上述代码中,JS会在执行setTimeout函数时停止执行,等待5秒后再执行包含一个循环的函数。循环的次数越多,JS需要执行的时间也越长,此时UI线程就会被卡住。因此,对于需要处理大量数据或需要等待较长时间的代码,必须使用其他方式避免阻塞主线程,例如Web Worker。