trigger click 和 click 的区别??
trigger click 和 user click 有什么区别吗?
好像没有的。直到发现了这样一段代码。
<button class="btn1">Button</button>
var btn1 = document.querySelector('.btn1');
btn1.addEventListener('click', function () {
Promise.resolve().then(function() {
console.log('Microtask 1');
})
console.log('Listener 1');
});
btn1.addEventListener('click', function () {
Promise.resolve().then(function() {
console.log('Microtask 2');
})
console.log('Listener 2');
});
点击click按钮会出什么结果呢?
Listener 1
Microtask 1
Listener 2
Microtask 2
那执行btn1.click()呢?
Listener 1
Listener 2
Microtask 1
Microtask 2
很神奇。
先来一个简单的问题
以下代码输出什么呢?
console.log('start')
setTimeout(()=>{
console.log('setTimeout')
}, 0)
Promise.resolve().then(function() {
console.log('promise1')
}).then(function() {
console.log('promise2')
})
console.log('end')
为什么会是这个顺序呢?先来个图讲解一下。

js的事件循环
看标题就知道原因就是事件循环了。
js是单线程驱动,执行的包含主线程(stack)和任务队列两部分,主线程负责处理同步任务,异步任务和回调会加到任务队列里面,每当主线程完成前一个任务,回调函数就会在一个无限循环圈里被调用,因此这个圈被称为事件循环。回调函数正在等待轮到自己执行所排的队就被称为任务队列。
还是没说到回调和异步的执行顺序?
macrotask 和 microtask
macrotask 和 microtask就是两个任务队列。举个例子:
macrotasks的操作 setTimeout setInterval setImmediate I/O UI渲染
microtasks的操作 Promise process.nextTick Object.observe MutationObserver
可以简单的理解为异步操作会加到macrotask队列,回调等监听操作会加到microtasks里。
那执行顺序是什么?
首先js会执行主线程(stack)的代码,就是同步的代码。这时候遇到异步操作怎么办?加到macrotask队列里准备执行回调加到 microtasks里准备执行。
主线程(stack)为空的时候,开始执行任务队列的代码。这是就开始了一个事件循环。
简单来说就3步:
- 在 macrotask 队列中执行最早的那个 task ,然后移出
- 执行 microtask 队列中所有可用的任务,然后移出
- 下一个循环,执行下一个 macrotask 中的任务 (再跳到第2步)
microtask queue 中的 task总是在当前的循环执行。
一份伪代码:
for (macroTask of macroTaskQueue) {
// 1. Handle current MACRO-TASK
handleMacroTask();
// 2. Handle all NEXT-TICK
for (nextTick of nextTickQueue) {
handleNextTick(nextTick);
}
// 3. Handle all MICRO-TASK
for (microTask of microTaskQueue) {
handleMicroTask(microTask);
}
}
每次执行macroTask的时候都会清空一下 microTask。
回到简单的问题。
这是我们再去看一下这个解释的gif。
console是同步任务,总是入stack,然后同步执行完。执行的过程settimeout会加到macrotask里,回调加到microtask里。
console完成了,stack为空,开始执行microtask,执行microtask的时候可以继续增加microtask,就像2个then。都执行完之后再执行macrotask的settimeout。
注意,run script 也是一个macrotask,所以执行stack的时候就是在执行第一个macrotask。所以当stack为空会先执行一次microtask。
回到code trigger和user trigger
dalao们应该已经知道为什么有区别了,其实就是macrotask和microtask的问题。
code trigger的时候,stack盏不是空的,所以两个click的microtask会顺序压入盏中,没有中断js的执行,当执行到btn1.click()的时候,stack空,顺序执行microtask。
推荐一篇相关文章,有图形化的讲解,特别清楚。click me。
requestanimationframe
requestanimationframe是一个比较特殊的api,对于它,浏览器只保证requestAnimationFrame的回调在重绘之前执行,没有确定的时间,何时重绘由浏览器决定。
所以有时候一样的代码执行结果不一样。
requestanimationframe属于macrotask。
拓展
async的异步调用
async的异步调用,其实还是promis的调用。看一下例子:
async function async1() {
console. log('async1 start' );
await async2();
console.log('async1 end' );
}
async function async2() {
console.log('async2');
}
console.log('script start' );
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
这个输出什么呢?
为什么async2在promise2前面呢?
看一下这个理解一下->
(来自阮一峰es6 - async的实现原理)
async function fn(args) {
// ...
}
// 等同于
function fn(args) {
return spawn(function* () {
// ...
});
}
function spawn(genF) {
return new Promise(function(resolve, reject) {
const gen = genF(); // 对应 console. log('async1 start' ),console.log('async2');
function step(nextF) {
let next;
try {
next = nextF();
} catch(e) {
return reject(e);
}
if(next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}
那么了解之后再看看这个?
async function async1() {
console. log('async start' );
await console.log('async2');
await console.log('async3');
await console.log('async4');
console.log('async end' );
}
console.log('script start' );
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
思考一下为什么async4,5之后的await都在promise2之前呢??
trigger click 和 click 的区别??的更多相关文章
- jQuery方法区别:click() bind() live() delegate()区别
今天看到一篇jquery 事件的文章,自己写了个小例子,虽然2种方式都可以实现,但是不太明白,找了点资料 $("#box1").delegate("p",&qu ...
- click()和onclick()的区别
click()和onclick()的区别: 1.onclick是绑定事件,告诉浏览器在鼠标点击时候要做什么 click本身是方法作用是触发onclick事件,只要执行了元素的click()方法,就会触 ...
- change和onchange、click和onclick的区别
change和onchange.click和onclick的区别: onchange和onclick都是js方法 可以在标签元素上使用 <input onchange="" ...
- 关于click和onclick的区别
click()和onclick()的区别: 1.onclick是绑定事件,告诉浏览器在鼠标点击时候要做什么 click本身是方法作用是触发onclick事件,只要执行了元素的click()方法,就会触 ...
- gulp die('click').live('click' composer
gulp die('click').live('click' composer packagist.org https://getcomposer.org/ 下载后 php composer.pha ...
- $("").click与onclick的区别
onclick是绑定事件,click本身是方法作用是触发onclick事件,只要执行了元素的click()方法,下面示例 Html代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- $("").click与onclick的区别示例介绍
Html代码: <script type="text/javascript"> $(function(){ $("#btn4").click(fun ...
- click和onclick的区别
onclick是绑定事件,click本身是方法作用是触发onclick事件,只要执行了元素的click()方法,下面有个示例,大家可以看看 Html代码 ? 1 2 3 4 5 6 7 8 9 1 ...
- javascript中click和onclick的区别
<script type="text/javascript"> $(function(){ $("#btn4").click(function(){ ...
随机推荐
- Java自学能学会吗?最新Java高级学习路线
就好像一千个人心中有一千个哈利波特一样,这个答案不绝对也不唯一,Java好学但自学的确阻力有些大,作为一门技术语言,它所蕴含的智慧绝对不是靠几本XX入门,XX框架之类的书所能概括,自学Java你要做好 ...
- ATS日志说明
在ATS日志中我们经常遇到形形色色的缓存结果码,为了更清晰地认识它们,相关资料整理到这里: TCP_HIT 请求对象的一份合法拷贝被缓存,ATS将发送该对象给client TCP_MISS 请求对象未 ...
- use zlib lib to compress or decompress file
If you want to compress or decompress file when writing C++ code,you can choose zlib library,that's ...
- Java对正则表达式的支持(一)
Java对正则表达式的支持主要体现在String.Pattern.Matcher和Scanner类. 1.Pattern.Matcher 先看一个Pattern和Matcher类使用正则表达式的例子. ...
- BZOJ 1367: [Baltic2004]sequence [可并堆 中位数]
1367: [Baltic2004]sequence Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1111 Solved: 439[Submit][ ...
- C语言之prinf的用法
1. n换行字符 1).直接输出内容 printf("哈哈\n"); 2).带参数的输出 int i = 10 ; %d:输入控制符 printf ("%d\n" ...
- 基于Spring Boot,使用JPA操作Sql Server数据库完成CRUD
完成一个RESTful服务,提供几个访问接口,用来操作较简单的联系人信息,数据保存在Sql Server数据库中. 1.使用STS创建工程. 使用STS创建RESTful工程,可以参考: <用S ...
- 使用websocket实现在线聊天功能
很早以前为了快速达到效果,使用轮询实现了在线聊天功能,后来无意接触了socket,关于socket我的理解是进程间通信,首先要有服务器跟客户端,服务的启动监听某ip端口定位该进程,客户端开启socke ...
- 理解Java Integer的缓存策略【转】
本文由 ImportNew - 挖坑的张师傅 翻译自 javapapers.欢迎加入翻译小组.转载请见文末要求. 本文将介绍 Java 中 Integer 缓存的相关知识.这是 Java 5 中引入的 ...
- zabbix安装笔记
部署监控安装zabbix时,安装环境选择位mysql5.6.29 php选5.4.45 环境安装:centOS7: yum install httpd php mariadb-server mysql ...