因为JavaScript是单线程执行的,意味着同一个时间点,只有一个任务在运行。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。
为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。
同步:一定要等任务执行完了,得到结果,才执行下一个任务。
异步:不等任务执行完,直接执行下一个任务。
比如
fn1()
fn2()
fn1执行完才执行fn2。
异步:不等任务执行完,直接执行下一个任务。
如如
function f1(){
setTimeout(function () {
console.log(1)
}, 1000);
}
function f2(){
console.log(2)
}
f1()
f2()
这段代码就是就是异步,f2没有等f1执行完毕就执行了。
常见的异步有:
setTimeout、Ajax请求、dom事件,他们都属于在浏览器的webApi中。异步是通过浏览器实现的,浏览器为这些耗时任务开辟了另外的线程。
图片来自Philip Roberts的演讲《Help, I'm stuck in an event-loop》
回调(callback)
浏览器把异步的任务放在callback queue中,要想拿到必须使用回调(callback),当JS里的栈stack清空时,说明一个任务已经执行完了,这时就会从callback queue中寻找下一个人任务推入栈中(这个寻找的过程,叫做event loop,因为它总是循环的查找任务队列里是否还有任务)。
所以简单说,通过webApi创建异步任务。任务完成时,如果有指定了回调函数,将回调函数放入task queue中;如果没有指定回调函数,这个事件就被丢弃。回调函数:定义了异步任务完成时所要执行的操作,包括事件和定时器所指定的异步任务。
比如
function f1(callback){
setTimeout(function () {
console.log(1)
callback();
}, 1000);
}
function f2(){
console.log(2)
}
f1(f2)
在1秒后f1执行结束,才会调用f2执行。
网友评论