setTimeout用法(Event Loop简介、for循环中应用、vue中应用)

vue

setTimeout基本用法

setTimeout(code,millisec)

setTimeout函数接受两个参数,第一个参数code是将要推迟执行的函数名或者一段代码,第二个参数millisec是推迟执行的毫秒数。

例如:

setTimeout(\'console.log(2)\',100);//直接在setTimeout中直接执行代码, 需要以字符串的形式去写,引擎内部会将字符串转为可执行的代码

setTimeout(function(){console.log(2)},100);

什么是 Event Loop

Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制。

JavaScript语言就采用这种机制,来解决单线程运行带来的一些问题。

在程序中设置两个线程:一个负责程序本身的运行,称为"主线程";另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")

上图主线程的绿色部分,还是表示运行时间,而橙色部分表示空闲时间。每当遇到I/O的时候,主线程就让Event Loop线程去通知相应的I/O程序,然后接着往后运行,所以不存在红色的等待时间。等到I/O程序完成操作,Event Loop线程再把结果返回主线程。主线程就调用事先设定的回调函数,完成整个任务。

可以看到,由于多出了橙色的空闲时间,所以主线程得以运行更多的任务,这就提高了效率。这种运行方式称为"异步模式"(asynchronous I/O)或"非堵塞模式"(non-blocking mode)。

执行顺序

console.log(1);

//Time1

setTimeout(function(){

console.log(2);

},300);for (var i = 0;i<10000;i++) {

console.log(4);

}

//Time2

setTimeout(function(){

console.log(3);

},300);

运行结果:循环中的方法会先执行,然后再执行settimeout中的方法。

 for循环中的setTimeout(异步操作)

function test() {

for (var i = 0; i < 5; ++i) {

setTimeout(function() {

console.log("index is :", i);

}, 1000);

}

}
test();

结果会显示:

该操作几乎是在同一时间完成,setTimeout定时根本就没有起作用,这是因为:单线程的js在操作时,对于这种异步操作,会先进行一次“保存”,for循环执行结束后,i的值已经变成5,setTimetout调用均是在for循环结束后进行的,所以自然而然输出都是5。一般情况下,我们使用递归实现:

function test(i) {

if (i< 5) {

console.log("index is :", i);

setTimeout(function() {

box7(i+ 1);

}, 1000)

}

}

test(0);

 我们也可以使用ES6中 async     Promise 实现,代码如下:

var asyncFunc = function(arr, i) {

return new Promise(function(resolve, reject) {

setTimeout(function() {

arr.push(i);

console.log("index is : ", i);

resolve();//异步操作完成后执行resolve方法,配合.then使用,本例子中未使用到。

}, 1000);

});

}

var box5 = async function() {

var arr = [];

for (var i = 0; i < 5; i++) {

await asyncFunc(arr, i);//async函数执行时,如果遇到await就会先暂停执行,等待Promise对象异步操作完成后,恢复async函数的执行并返回解析值。

}

console.log(arr);

}

box5();

 补充20200611:

解决办法一

for (var i = 0; i < 5; i++) { 

(function(i){ //立刻执行函数

setTimeout(function (){

console.log(i);

},1000);

})(i);

}

这里用到立刻执行函数。这样 console.log(i); 中的i就保存在每一次循环生成的立刻执行函数中的作用域里了。

解决办法二

for (let i = 0; i < 5; i++) {     //let 代替 var

setTimeout(function (){

console.log(i);

},1000);

}

let 为代码块的作用域,所以每一次 for 循环,console.log(i); 都引用到 for 代码块作用域下的i,因为这样被引用,所以 for 循环结束后,这些作用域在 setTimeout 未执行前都不会被释放。

setTimeout在vue中应用

vue中直接使用this,此时的this指向的是window对象,虽然end方法仍然被执行了,但是没有延迟1s后执行的效果。

setTimeout(this.end(),1000);

正确的做法是方法中将this存在变量that中,此时执行setTimeout函数时,setTimeout函数内的that就会访问到这个变量,就会得到当前对象。

export default {

methods: {

start: function () {

let that=this

setTimeout(function() {

that.end()

}, 1000);

}

}

也可以使用箭头函数:

export default {

methods: {

start: function () {

setTimeout(() => {

this.end()

}, 1000);

}

}

 参考:

http://www.ruanyifeng.com/blog/2013/10/event_loop.html

以上是 setTimeout用法(Event Loop简介、for循环中应用、vue中应用) 的全部内容, 来源链接: utcz.com/z/380949.html

回到顶部