首页 > 作文

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

更新时间:2023-04-05 04:34:57 阅读: 评论:0

异步

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

青青子衿悠悠我心一段简单的小程序

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

console.log("a");ttimeout(() => {  console.log("b");}, 100);console.log("c");

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

对类似程序的解释通常是由 ttimeout 设置一个定时器,在指定毫秒数后调用回调函数。然而,它的执行机制并不是这么简单。实际上,ttimeout 的作用是在指定的毫秒数之后,在得到机会时,将 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。

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

chunk1执行:由 ttimeout 启动定时器(100毫秒)chunk2执行:得到机会,将 callback 放入 event loop queuechunk3执行:此 callback 执行

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

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

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

一些简单的小例子

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

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

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

再看下一个。

下面的堆栈信息会输出 c – b – a 吗?

ttimeout(function a() {  ttimeout(function b() {    ttimeout(function c() {      throw new error("error - from function c");    }, 0);  }, 0);}, 0);

它们并不对应同一条 event loop queue 中的消息,分别有各自的调用栈,所以错误栈里面只有 c。

job queue

job 是 es6 中新增的概念,它与 promi 的执行有关,可以理解为等待执行的任务;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 中,一个 pr他生气了作文300字omi 就是一个 promijob,一种 job。

再来观察一段小程序:

console.log("a");ttimeout(() => {  console.log("a - ttimeout");}, 0);new promi((resolve) => {  resolve();}).then(() => {  return console.log("a - promi 1");}).then(() => {  return console.log("b - promi 1");});new promi((resolve) => {  resolve();}).then(() => {  return console.log("a - promi 2");}).then(() => {  return console.log("b - promi 2");}).t**粗体文字**hen(() => {  return console.log("c - promi 2");});console.log("aa");

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

a

aa

a – promi 1

a – promi 2

b – promi 1

b – promi 2

c – promi 2

a – ttimeout

理解这个输出:

a 与 aa 最先输出,因为它们不是异步任务,属于第一个 chunk。promi 1 与 promi 2 先于 ttimeout 执行,因为 job queue 的执行优先于 event loop queue。promi 1 与 promi 2 各自的输出都是顺序的,因为 job queue 是先进先出队列,同一 job queue 中的任务顺序执行。promi 1 与 promi 2 的后续任务是交错的,因为 promi 1 与 promi 2 都是独立的 promijob(job 的其中一种),属于不同的 job queue,它们之间的顺序规范中没有规定。

并发

文章开头,我说「简单地说,javas李峤的风cript 是单线程执行的语言」,现在可以说得稍微复杂一点了: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异步编程:设计快速响应的网络应用

本文发布于:2023-04-05 04:34:56,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/15fe158190720fe95398e331d0fd4a78.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:js延迟1秒的方法(javascript延时函数).doc

本文 PDF 下载地址:js延迟1秒的方法(javascript延时函数).pdf

上一篇:烟碱中毒
下一篇:返回列表
标签:都是   顺序   队列   程序
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图