步子百科步子百科

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

异步

简单来说,延迟延Javascript 它是函数一种单线程语言,但在应用程序中有许多异步执行现象。延迟延异步本质上是函数以多种方式(相对相同)操作程序的执行顺序,这不同于其他语言中的延迟延多线程模型,所以人们经常使用非顺序 Javascript 编码的函数操作结论感到困惑。

一个简单的延迟延小程序

一切用过 Javascript 程序员可以说出以下编码的导出:

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

顺序是 A、C、函数B,延迟延由于第二个参数是函数特定延迟的ms数,这段编码只有一个 setTimeout,延迟延所以不会让人蒙蔽。函数

类似程序的延迟延解释通常是由类似程序解释的 setTimeout 在规定中设置计时器ms回调函数在数后启用。但它的函数执行机制并不那么简单。事实上,延迟延setTimeout 功能是指定的ms数数之后,得到机会的时候,会 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 运行计时器(100ms) chunk2实施:获得机会,将获得机会, callback 放进 Event Loop Queue chunk3实行:此 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异步编程:设计快速反应的网络应用