想象下,比如浏览器在运行一个复杂的图像转换算法,因为是单线程的,所以此时浏览器进程被阻塞了,不能进行界面渲染,也不能运行其他代码,你的应用界面会失去和用户的交互。
这一般情况下还不会有大问题,但是当浏览器在同时运行多个类似的算法时,这个问题就很严重了。
有一定经验js开发人员大多都理解代码的异步执行,特别是ajax的使用。
// ajax(..) is some arbitrary Ajax function given by a library var response = ajax('https://example.com/api'); console.log(response); // `response` won't have the response
这里response 将不会得到你想要的结果。
而是需要像相面这样,通过 callback函数的方式,获取结果
ajax('https://example.com/api', function(response) { console.log(response); // `response` is now available });
另外这里面提醒一下,下面的代码, async: false永远都不是一个好主意。
// This is assuming that you're using jQuery jQuery.ajax({ url: 'https://api.example.com/endpoint', success: function(response) { // This is your callback. }, async: false // And this is a terrible idea });
通过上面的例子,我们应该理解通过 异步 函数,可以帮助我们解决 类似浏览器阻塞问题。
当然还可以通过 setTimeout(callback, milliseconds)实现同样的逻辑。如果你理解了异步,下面代码执行会输出什么呢?
function first() { console.log('first'); } function second() { console.log('second'); } function third() { console.log('third'); } first(); setTimeout(second, 1000); // Invoke `second` after 1000ms third();
那个这下异步处理机制的原理是什么呢?这里就要引入我们的事件循环Event Loop了
Event Loop有一个简单的Job(task) - 监视Call Stack和Callback Queue。如果调用堆栈为空,它将从队列中取出第一个事件,并将其推送到调用堆栈,从而有效地运行它。
这种迭代在事件循环中被称为Tick。每个事件只是一个函数回调。
console.log('Hi'); setTimeout(function cb1() { console.log('cb1'); }, 5000); console.log('Bye');
执行这段代码,下面的调用栈清楚的演示了事件循环的处理流程。
请注意,setTimeout(...)不会自动将您的回调放在事件循环队列中。
它设置了一个计时器。当计时器到期时,浏览器将你的回调放到事件循环中,以便将来的一些tick会执行。但是,队列中可能还有其他事件已经被添加了 - 您的回调将不会立即执行。
有很多关于开始使用JavaScript中的异步代码的文章和教程,建议您使用setTimeout(callback,0)。
现在你知道Event Loop是怎么做的,以及setTimeout是如何工作的。
你就能更好的理解下面的代码
console.log('Hi'); setTimeout(function() { console.log('callback'); }, 0); console.log('Bye');
尽管等待时间设置为0 ms,但浏览器控制台中的结果如下所示:
Hi
Bye
callback
事件循环所做的正如它的名字所说的。它运行在一个循环里,直到它的终止。这符合网络框架的设计,因为他们需要在一个循环为一个特定的连接运行事件。这不是 Netty 发明新的东西;其他框架和实现已经这样做了。 下面的清单显示了典型的 EventLoop 逻辑。请注意这是为了更好的说明这个想法而不是单单展示 Netty 实现本身。 Listing 14.1 Execute task in EventLoop
本文向大家介绍Eventloop的理解?相关面试题,主要包含被问及Eventloop的理解?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 任务队列中,在每一次事件循环中,macrotask只会提取一个执行,而microtask会一直提取,直到microsoft队列为空为止。 也就是说如果某个microtask任务被推入到执行中,那么当主线程任务执行完成后,会循环调用该队列任务中的下一个任
JavaScript 介绍 前端开发三要素,HTML(描述网页内容),CSS(描述样式),JavaScript(控制网页行为)。JavaScript 为解释型编程语(程序不需要编译,程序在运行时才翻译成机器语言,每执 行一次都要翻译一次),运行环境也很广泛(浏览器或操作系统中 NodeJS)。 JavaScript 又分为两部分,ECMAScript 和 DOM。其中 JavaScript 的基本
本文向大家介绍JavaScript中的闭包介绍,包括了JavaScript中的闭包介绍的使用技巧和注意事项,需要的朋友参考一下 所谓的闭包应该是指: 内部函数读取当前函数以外的变量,即创建时所处的上下文环境。 需要注意的是这里的print函数引用了外部hello函数的char变量,于是在这里我们能够返回一个 而这个功能在某种意义上来说,应该是要归功于作用域。当然了,我们没有办法直接访问char,除
本文向大家介绍Javascript中的call()方法介绍,包括了Javascript中的call()方法介绍的使用技巧和注意事项,需要的朋友参考一下 在Mozilla的官网中对于call()的介绍是: Call() 语法 Call() 参数 thisArg arg1, arg2, ... Javascript中的call()方法 先不关注上面那些复杂的解释,一步步地开始这个过程。 Call()方
本文向大家介绍JavaScript中的console.trace()函数介绍,包括了JavaScript中的console.trace()函数介绍的使用技巧和注意事项,需要的朋友参考一下 调试JavaScript程序时,有时需要打印函数调用的栈信息,这可以通过使用console.trace()来实现。以下面的代码为例: 在doSubTask()函数的执行结尾处插入了一行console.trace(