setTimeout用法(Event Loop简介、for循环中应用、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 代替 varsetTimeout(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