js 关于setTimeout和Promise执行顺序问题

异步 -- Promise和setTimeout 执行顺序

 

Promise 和 setTimeout 到底谁先执行

Chrome开发工程师一篇文章
浏览器异步和单线程的问题

定时器的介绍

1.首先js是单线程,单线程的解释'单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须'
'处理好,后面的才会执行。' 2.setTimeout 是JavaScript 是运行于单线程的环境中的,是计划代码在未来的某个时间执行
'setTimeout'的作用是在间隔一定的时间后,将回调函数插入消息队列中,等栈中的同步任务都执行完毕后,再执
行。因为栈中的同步任务也会耗时,所以间隔的时间一般会大于等于指定的时间。
'setTimeout(fn, 0)'的意思是,将回调函数fn立刻插入消息队列,等待执行,而不是立即执行 3.执行时机是不能保证的,因为在页面的生命周期中, 不同时间可能有其他代码在控制 JavaScript 进程 4.在页面下载完后的'代码运行'、'事件处理程序'、'Ajax 回调函数'都必须使用同样的'线程来执行',浏览器负责
'进行排序',指派'某段代码'在'某个时间点'运行的'优先级'。 5.主 JavaScript 执行进程外,还有一个需要在进程下一次空闲时执行的代码队列。随着页面在其
生命周期中的推移,代码会按照执行顺序添加入队列。
5.1.例如,当某个按钮被按下时,它的事件处理程序代码就会被添加到队列中,并在下一个可能的时间里
执行。当接收到某个' Ajax 响应时','回调函数'的代码会被'添加到队列'。在 JavaScript 中没有任何代
码是立刻执行的,但一旦进程空闲则尽快执行。 6.定时器的工作机制也是类似:'当特定时间过去后'将'代码插入'。注意,给队列添加代码并'不意味着对 它立刻执行',
而只能'表示它会尽快执行'。设定一个 150ms 后执行的定时器不代表到了 150ms 代码就立刻 执行,它表示代码
'会在 150ms 后被加入到队列中'
7.如果在这个时间点上,队列中没有其他东西,那么这 段代码就会被执行,表面上看上去好像代码就在精确指定
的时间点上执行了。其他情况下,'代码可能明显地等待更长时间才执行。'
JavaScript高级程序设计(第3版)中的一个案例来说明定时器会延迟执行
1.下面代码有一个点击事件,当点击事件结束触发,会触发里面的定时器,那么定时器真的会在事件触发的250ms
后执行么?
答案:尽管在 255ms 处添加了定时器代码,但这时候还不能执行,因为 onclick 事件处 理程序仍在运行。
定时器代码最早能执行的时机是在 300ms 处,即 onclick 事件处理程序结束之后。

var btn = document.getElementById("my-btn");
btn.onclick = function(){
setTimeout(function(){
document.getElementById("message").style.visibility = "visible";
}, 250);
//其他代码
};
小技巧连续的定时器
1.setInterval() 是连续执行的定时器,这个会有一个弊端像下面图一样:
定时器是在 205ms 处添加到队列中的,但是直到过了 300ms 处才能够执行第一个定时器。当执行
这个定时器代码时,在 405ms 处又给队列添加了另外一个副本。在下一个间隔,即 605ms 处,第一
个定时器代码仍在运行,同时在队列中已经有了一个定时器代码的实例。结果是,在这个时间点上的
定时器代码不会被添加到队列中。结果在 5ms 处添加的定时器代码结束之后,405ms 处添加的定时器代码
就立刻执行。

  • 使用链式setTimeout() 解决
1.每次函数执行的时候都会创建一个新的定时器。第二个 setTimeout()调用使用了 arguments.callee 来获取对
当前执行的函数的引用,并为其设置另外一 个定时器。这样做的好处是,在前一个定时器代码执行完之前,
不会向队列插入新的定时器代码,确保 不会有任何缺失的间隔
setTimeout(function(){
//处理中
setTimeout(arguments.callee, interval);
}, interval);
  • 书中一个元素向右移动,当左坐标在 200 像素的时候停止的案例
setTimeout(function(){
var div = document.getElementById("myDiv");
left = parseInt(div.style.left) + 5;
div.style.left = left + "px";
if (left < 200){
setTimeout(arguments.callee, 50);
}
}, 50);

Promise 和 setTimeout 的执行顺序

1.Promise 和 setTimeout 都是异步,都会被在特定时间添加到队列中,那么到底谁会先执行?
2.首先要弄清'任务'和'微观任务',在'setTimeout'章节已经可以知道因为'js是单线程的缘故'所以
他需要对执行'任务'进行类似队列来决定他们的执行顺序触发时机,在任务中还有一种任务叫
'微观任务(Microtasks)'
一个说明的案例
1.下面代码打印结果为'a,b,c,d',先打印'a'在打印'b' 因为代码的先后执行顺序先依次'a' 和'b' 但是'c'
和'd' 都是异步他们的先后执行显而易见不会因为他们代码执行顺序先后而依次打印。
2.首先'Promise ':需要进行 io、等待或者其它异步操作的函数,不返回真实结果,而返回一'承诺',
函数的调用方可以在合适的时机,选择等待这个承诺兑现(通过 Promise 的 then 方法的回调)
3.这里可以简单的理解这两个异步:'Promise 属于我们说的微观任务,setTimeout 属于任务',因此
'Promise 永远在队列尾部添加微观任务。setTimeout 等宿主 API,则会添加任务。'因此可以得到
一个结论'作为微观任务的代表Promise这个异步会直接在特定情况下添加到对应队列执行尾部',
'setTimeout 则会根据调用他的宿主api执行了才把自己放到尾部'
4.因此'Promise 会比setTimeout先执行'
var r = new Promise(function(resolve, reject){
console.log("a");
resolve()
});
setTimeout(()=>console.log("d"), 0)
r.then(() => console.log("c"));
console.log("b")
再来一个极端的案例接着说明
1.我们延迟Promise执行时间,增加到1s,这时候打印结果如果按照我们的猜想,即使'Promise'延迟了
你'setTimeout'也要排在我的后面,因为我'Promise' 就是比你先进队列的不服你也给等着'我微观任务'
就是牛逼因此打印结果'c1 c2 d'
2.根据' 极客时间 winter老师的总结'这里要说明根据谷歌浏览器的开发博客我们可以知道没有'宏观任务的说法'
只有微观任务和任务的说法我这里理解'winter是为了让大家更好的理解将任务比喻成宏观任务':
2.1.首先我们分析有多少个宏任务;
2.2.在每个宏任务中,分析有多少个微任务;根据调用次序,确定宏任务中的微任务执行次序;
2.3.根据宏任务的触发规则和调用次序,确定宏任务的执行次序;
2.4.确定整个顺序。
setTimeout(()=>console.log("d"), 0)
var r = new Promise(function(resolve, reject){
resolve()
});
r.then(() => {
var begin = Date.now();
while(Date.now() - begin < 1000);
console.log("c1")
new Promise(function(resolve, reject){
resolve()
}).then(() => console.log("c2"))
});
  • 一个很有意思的属性'MutationObserver'

js 关于setTimeout和Promise执行顺序问题的更多相关文章

  1. 宏任务和微任务:setTimeout和Promise执行顺序

    先以一道面试题做引子: 写出这段程序的输出内容: setTimeout(function(){ console.log(); },); new Promise(function(a,b){ conso ...

  2. 关于setTimeout和Promise执行顺序问题

    先看一段代码 console.log('打印'+1); setTimeout(function(){ console.log('打印'+2); }) new Promise(function(reso ...

  3. wex5 实战 wex5与js的组件关系与执行顺序(父子与先后)

    初学wex5,先理理让人容易混淆的三个概念: 一 基本概念: 1 wex5组件,顾名思义,在编辑窗口右侧的组件集合里的,都是wex5基于开源自创的组件,并封装了一套自已的方法.目的是为了方便.相关方法 ...

  4. JS的预编译和执行顺序 详析

    原文:JS的预编译和执行顺序 详析 最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题   代码:   复制代码 代码一 <ht ...

  5. JS中For循环中嵌套setTimeout()方法的执行顺序

    在For循环中执行setTimeOut()方法的代码,执行顺序是怎样的呢? 代码如下 function time() { for(var i= 0;i<5;i++){ setTimeout(fu ...

  6. JS的预编译和执行顺序 详析(及全局与局部变量)

    最近在复习javascript的事件处理时发现了一个问题,于是总结一下:javascript的预编译和执行顺序的问题:   <html> <head> <title> ...

  7. JS day01——window对象、执行顺序、线程模型

    1.window对象 window对象表示当前浏览器的窗口,它是一个顶级对象,我们创建的所有对象.函数.变量都是window对象的成员. window对象自带了一些非常有用的方法.属性. window ...

  8. js函数和变量的执行顺序【易错】

    js函数和变量的声明与执行顺序 一.函数执行顺序 1.正常顺序 function f(){ alert(2); } f(); //alert 2 所有浏览器都能测试通过. 2.倒序调用 f(); // ...

  9. 再次聊一聊promise settimeout asycn awiat执行顺序---js执行机制 EVENT LOOP

    首先js是单线程 分为同步和异步,异步又分为(macrotask 宏任务 和 microtask微任务 ), 这图还是很清晰嘛,再来一张 总结一下,就是遇到同步先执行同步,异步的丢到一边依次排队,先排 ...

随机推荐

  1. python3中map()函数用法

    python源码解释如下:map(func, *iterables) --> map objectMake an iterator that computes the function usin ...

  2. Centos部署Loki日志聚合系统

    关于一些日志聚合由来及原理科普见我的另外一篇 <编程入门之日志聚合系统> https://www.cnblogs.com/uncleguo/p/15948763.html Loki日志聚合 ...

  3. 实现同比、环比计算的N种姿势

    在做数据分析时,我们会经常听到同比.环比同比的概念.各个企业和组织在发布统计数据时,通常喜欢用同比.环比来和之前的历史数据进行比较,用来说明数据的变化情况.例如,统计局公布2022年1月份CPI同比增 ...

  4. 极速体验|使用 Erda 微服务观测接入 Jaeger Trace

    在大型网站系统设计中,随着分布式架构,特别是微服务架构的流行,我们将系统解耦成更小的单元,通过不断的添加新的.小的模块或者重用已经有的模块来构建复杂的系统.随着模块的不断增多,一次请求可能会涉及到十几 ...

  5. Adobe photoshop CS6 + 破解补丁

    软件位置: 链接:https://pan.baidu.com/s/1KeKRS0yIMfeEbOJQ-ilo0g 破解流程 首先断开网络连接 (如果不断网安装过程中会要求登陆)打开Photoshop ...

  6. 自己动手写Vector【Cherno C++教程】

    动手写一个Vector 本文是对<最好的C++教程>的动手写数据结构部分的一个整理,主要包含91p动手写Array数组和92p动手写Vector数组的内容. 自己动手来写这些数据结构是学习 ...

  7. 盘点十大GIS相关算法

    1.道格拉斯-普克算法(Douglas–Peucker) 道格拉斯-普克算法(Douglas–Peucker algorithm,亦称为拉默-道格拉斯-普克算法.迭代适应点算法.分裂与合并算法)是将曲 ...

  8. hadoop学习笔记 一

    Hadoop 2.x * common * HDFS 存储数据 NameNode 主从结构 * 存储文件系统的元数据,命名空间namespace DataNode * 存储数据 SecondaryNa ...

  9. Apple macOS Mojave Intel Graphics Driver组件任意代码执行漏洞

    受影响系统:Apple macOS Mojave 10.14.5描述:CVE(CAN) ID: CVE-2019-8629 Apple macOS Mojave是苹果公司Mac电脑系列产品的操作系统. ...

  10. php——新闻项目改写

    主要思路:遵守java开发规范,保持接口一致性 如何保持接口的一致性: (1).url的一致性:使用@RequestingMapping注解 (2).参数的一致性: 使用@ReuqestParam注解 ...