本文主要理解一下 setTimeout 和回调函数的执行原理。
大家都知道,JavaScript 的是单线程的,所有的行为都会在一个线程中排队完成。在一个任务执行过程中时,是无法执行其他任务的。如果某个任务执行时间过长,那么界面就会整个浏览器就会处在假死状态,甚至出现下面的情况。这时候用户体验就直接 GG 了。
GG这时候异步就登场了~而异步最开始的形式就是回调函数了。比如 ajax:
ajax('https://example.com/api', function(response) {
console.log(response); // `response` 现在有值
});
ajax 中的第二个参数就是异步回调函数了,我对它的理解是现在发起异步请求,等待未来某个时间响应后执行回调函数。
下面是一个 setTimeout 延时执行的例子:
console.log('Hi');
setTimeout(function cb1() {
console.log('cb1');
}, 5000);
console.log('Bye');
可以通过下面的动图理解一下回调函数队列:
image从图中可以看到,执行一个 setTimeout 主要需要三个部分:
- 调用栈(执行 JavaScript 代码的地方)
- 回调队列(异步执行函数队列)
- WEB APIs(提供定时器的宿主)。
具体步骤如下:
- 在调用栈中执行了 setTimeout 方法
- 交给了浏览器 API 来进行计时行为
- 等时间到了之后将回调函数加入回调队列
- 当调用栈清空之后将回调函数推入调用栈执行
所以说,setTimeout(cb, 3000)
并不是说 3 秒后立即执行,更应该说是 3 秒后加入回调函数队列开始执行。只有执行完调用栈中的代码后(调用栈清空)才会将回调队列中的方法加入到调用栈中执行。
查看如下代码:
console.log('Hi');
setTimeout(function() {
console.log('callback');
}, 0);
console.log('Bye');
根据上面的理论,console.log('callback');
经过 0 秒加入了回调函数队列,等到调用栈清空后才会被执行。打印结果如下:
Hi
Bye
callback
这次真正认识到了回调函数的执行方式。
最后
放荡了几天,发现不日更博客自己都没有了学习和思考的动力。决定还是要坚持。每天给自己留点要做的事情,挤出一些时间学习和思考,乘着年轻努力成长,见识更大的世界。
而对于像我这种又不聪明、没背景的人,想让自己变得成长也只能靠坚持了。一起加油吧不枉年轻一回
网友评论