当前位置:首页 > 生活百科

js延迟1秒的方法(javascript延时函数)

栏目:生活百科日期:2025-01-21浏览:0

异步

简单地说,JavaScript 是单线程执行的语言,但在使用中有很多异步执行的情况。异步的本质是用其他方式(相对同步)控制程序的执行顺序,这与其他语言中的多线程模型不同,所以常常有人对非顺序 JavaScript 代码的运行结果感到困惑不解。

一段简单的小程序

任何使用过 JavaScript 的程序员都能说出下面这段代码的输出:

console.log("A");setTimeout(() =&> {  console.log("B");}, 100);console.log("C");

先后顺序是 A、C、B,因为第二个参数的作用是指定延迟的毫秒数,这段代码只有一个 setTimeout,所以不会让人迷惑。

对类似程序的解释通常是由 setTimeout 设置一个定时器,在指定毫秒数后调用回调函数。然而,它的执行机制并不是这么简单。实际上,setTimeout 的作用是在指定的毫秒数之后,在得到机会时,将 callback 放入 Event Loop Queue。

Event Loop

首先要抛出一些概念,通常所说的 JavaScript Engine 是指负责执行一个一个 chunk 的程序,它依赖宿主环境的调度,也需要通过宿主环境与操作系统产生关联并得到支持。JavaScript Engine 是 JavaScript Runtime(Hosting Environment) 的一部分。

每个 chunk 通常是以 function 为单位,一个 chunk 执行完成后,才会执行下一个 chunk。下一个 chunk 是什么呢?取决于当前 Event Loop Queue 中的队首。Event Loop Queue 中存放的都是消息,每个消息关联着一个函数,JavaScript Engine 就按照队列中的消息顺序执行它们,也就是执行 chunk。

所以上面的 setTimeout 实际执行起来更接近这样:

chunk1执行:由 setTimeout 启动定时器(100毫秒)chunk2执行:得到机会,将 callback 放入 Event Loop Queuechunk3执行:此 callback 执行

不难发现,得到机会很重要!这也就可以解释用 setTimeout 延迟 1000 不一定是准确的,而是会至少延迟一秒。因为如果还有其他的任务在前面,它要等待那些任务对应的消息都出队,也就是程序都执行完成,它才能将 callback 放入队列。也就是实际延迟会大于或等于一秒。

通常所说的触发了一个事件,就是指这个 event listener 得到了执行。与 setTimeout 这个例子中的概念一样,这也是一次 chunk 的执行。像这样一个一个执行 chunk 的过程就叫 Event Loop

还有一个经常提到的概念叫「无阻塞」,JavaScript 中的无阻塞就是指这种 Event Loop 模型。除去 alert 或同步 Ajax 请求等历史原因造成的问题,程序总是不会出现阻塞;也就是说 JavaScript Engine 总是可以处理下一个任务,如处理用户对浏览器的操作。

一些简单的小例子

将 setTimeout 加入 try 语句之中,结果会如何?

try {  setTimeout(() =&> {    throw new Error("Error - from try statement");  }, 0);} catch (e) {  console.error(e);}

try catch 与 setTimeout 不在同一个 chunk,所以……你懂的。

再看下一个。

下面的堆栈信息会输出 C &– B &– A 吗?

setTimeout(function A() {  setTimeout(function B() {    setTimeout(function C() {      throw new Error("Error - from function C");    }, 0);  }, 0);}, 0);

它们并不对应同一条 Event Loop Queue 中的消息,分别有各自的调用栈,所以错误栈里面只有 C。

Job Queue

Job 是 ES6 中新增的概念,它与 Promise 的执行有关,可以理解为等待执行的任务;Job Queue 就是这种类型的任务的队列。JavaScript Runtime 对于 Job Queue 与 Event Loop Queue 的处理有所不同。

相同点:

都用作先进先出队列

相异点:

每个 JavaScript Runtime 可以有多个 Job Queue,但只有一个 Event Loop Queue当 JavaScript Engine 处理完当前 chunk 后,优先执行所有的 Job Queue,然后再处理 Event Loop Queue

ES6 中,一个 Promise 就是一个 PromiseJob,一种 Job。

再来观察一段小程序:

console.log("A");setTimeout(() =&> {  console.log("A - setTimeout");}, 0);new Promise((resolve) =&> {  resolve();}).then(() =&> {  return console.log("A - Promise 1");}).then(() =&> {  return console.log("B - Promise 1");});new Promise((resolve) =&> {  resolve();}).then(() =&> {  return console.log("A - Promise 2");}).then(() =&> {  return console.log("B - Promise 2");}).t**粗体文字**hen(() =&> {  return console.log("C - Promise 2");});console.log("AA");

在原生支持 Promise 的环境,输出是这样:

A

AA

A &– Promise 1

A &– Promise 2

B &– Promise 1

B &– Promise 2

C &– Promise 2

A &– setTimeout

理解这个输出:

A 与 AA 最先输出,因为它们不是异步任务,属于第一个 chunk。Promise 1 与 Promise 2 先于 setTimeout 执行,因为 Job Queue 的执行优先于 Event Loop Queue。Promise 1 与 Promise 2 各自的输出都是顺序的,因为 Job Queue 是先进先出队列,同一 Job Queue 中的任务顺序执行。Promise 1 与 Promise 2 的后续任务是交错的,因为 Promise 1 与 Promise 2 都是独立的 PromiseJob(job 的其中一种),属于不同的 Job Queue,它们之间的顺序规范中没有规定。

并发

文章开头,我说「简单地说,JavaScript 是单线程执行的语言」,现在可以说得稍微复杂一点了:JavaScript Engine 对 JavaScript 程序的执行是单线程的,但是 JavaScript Runtime(整个宿主环境)并不是单线程的;而且,几乎所有的异步任务都是并发的,例如多个 Job Queue、Ajax、Timer、I/O(Node)等等。

上面说的是 JavaScript Runtime 层面,JavaScript 执行本身,也有一些特殊情况,例如:一个 Web Worker 或者一个跨域的 iframe,也是独立的线程,有各自的内存空间(栈、堆)以及 Event Loop Queue。要与这些不同的线程通信,只能通过 postMessage。一次 postMessage 就是在另一个线程的 Event Loop Queue 中加入一条消息。

参考资料

Concurrency model and Event Loop

ECMAScript? 2015 Language Specification

You Don’t Know JS: Async && Performance

JavaScript异步编程:设计快速响应的网络应用

“js延迟1秒的方法(javascript延时函数)” 的相关文章

什么是3d电影,简述3d电影和传统电影的区别

如今广泛的电影使用数字图像让3D电影技术得以复苏。3D是一种数字视觉效果技术,主要用于那些以特效为主的影片当中。“3D电影”这个概念实际上并不是那么准确,因为传...

proteus怎么添加直流电压源(详解proteus交流电压源设置

1.基于proteus的51单片机开发实例22-L298N驱动直流电机1.1.实验目的图1L298驱动直流电机在上一实例中,我们使用H桥驱动直流电机实现正转、反...

公司注册资本多少有什么关系(几个案例告诉你最大的区别

按照修订的《公司法》及相关条例,“注册资本”的登记管理已经从“实缴登记制”调整为“认缴登记制”,也就是说注册资本的实缴已经没有期限承诺限制,也没有认缴最低限额,...

2020年养猪成本和利润分析(养猪利润及风险真相大揭秘)

对于猪场来说,不同的养猪水平,不同的疫病状况,不同的原料价格,不同节点的生猪行情,养猪成本与利润都有明显差异。2020年,养猪成本历史新高,养猪利润史无前例20...

什么是悟空理财,悟空理财可靠安全吗_1

自从金融理财搭上了互联网的顺风车,“旧时王谢堂前燕”——几年前还仿佛高高在上拒普通民众千里之外的高门槛理财产品已经“飞入寻常百姓家”。市面上的理财品种琳琅满目...

es文件浏览器tv版教程(比es更好用的文件浏览器)

谈及现在不少家庭都在用的智能电视,智能盒子,大多都是以谷歌安卓系统进化改进而来的,简单说他们的核心都是谷歌安卓,和安卓手机一样可以支持所有安卓应用程序的安装和使...

dxf是什么文件格式(系统备份文件格式分析)

虽然三维设计已经在很多企业的研发设计部门很普遍的应用,也有很多的企业设计部门完全的使用三维软件进行设计和出图,但是由于生产和外协的缘故,还需要给相关人员转换成C...

excel选取部分字段公式(excel提取不规则字段)

Excel表格中要选取一个单元格,很简单,鼠标点击即可选中,那么选取多个单元格呢?也就是单元格区域,单元格少还可以拖动选择。如果有数千行、列要选取呢?还是拖动选...

品牌推广活动案例分享,品牌推广策略包括哪些内容

改变了中国消费生态的双十一,竞争越来越大,品牌以往的双十一打法显然已经不再适用于瞬息万变的中国消费市场。消费者对品牌的敏感度正在降低,对双十一的激情也不如以前,...

三星s4上市价格多少(三星2023即将上市智能手表)

目前市面上的手机更新换代都非常快,这样造成的一个问题就是。上代旗舰的保值问题,在这方面苹果的iPhone最强。而其他所有厂商都不是很给力。不过这也给了我们购买手...