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步:

  1. 在 macrotask 队列中执行最早的那个 task ,然后移出
  2. 执行 microtask 队列中所有可用的任务,然后移出
  3. 下一个循环,执行下一个 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 的区别??的更多相关文章

  1. jQuery方法区别:click() bind() live() delegate()区别

    今天看到一篇jquery 事件的文章,自己写了个小例子,虽然2种方式都可以实现,但是不太明白,找了点资料 $("#box1").delegate("p",&qu ...

  2. click()和onclick()的区别

    click()和onclick()的区别: 1.onclick是绑定事件,告诉浏览器在鼠标点击时候要做什么 click本身是方法作用是触发onclick事件,只要执行了元素的click()方法,就会触 ...

  3. change和onchange、click和onclick的区别

    change和onchange.click和onclick的区别: onchange和onclick都是js方法 可以在标签元素上使用  <input  onchange="" ...

  4. 关于click和onclick的区别

    click()和onclick()的区别: 1.onclick是绑定事件,告诉浏览器在鼠标点击时候要做什么 click本身是方法作用是触发onclick事件,只要执行了元素的click()方法,就会触 ...

  5. gulp die('click').live('click' composer

    gulp  die('click').live('click' composer packagist.org https://getcomposer.org/ 下载后 php composer.pha ...

  6. $("").click与onclick的区别

    onclick是绑定事件,click本身是方法作用是触发onclick事件,只要执行了元素的click()方法,下面示例 Html代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 ...

  7. $("").click与onclick的区别示例介绍

    Html代码: <script type="text/javascript"> $(function(){ $("#btn4").click(fun ...

  8. click和onclick的区别

    onclick是绑定事件,click本身是方法作用是触发onclick事件,只要执行了元素的click()方法,下面有个示例,大家可以看看   Html代码 ? 1 2 3 4 5 6 7 8 9 1 ...

  9. javascript中click和onclick的区别

    <script type="text/javascript"> $(function(){ $("#btn4").click(function(){ ...

随机推荐

  1. c# 基础任务1

    1.winform系统全局异常布局处理. Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);   ...

  2. 03_HTML Canvas第一天

    视频来源:麦子学院 讲师:刘慧涛 w3cshool之HTML5画布:http://www.w3school.com.cn/html5/html_5_canvas.asphtml5 canvas参考手册 ...

  3. 【转】python入门指引

    http://matrix.42qu.com/10757179 前言 其实我也不知道python怎么入门,由我来写这个真的不是很合适.我学python是直接找了dive into python来看.然 ...

  4. 【视频编解码·学习笔记】5. NAL Unit 结构分析

    在上篇笔记中通过一个小程序,可以提取NAL Unit所包含的的字节数据.H.264码流中的每一个NAL Unit的作用并不是相同的,而是根据不同的类型起不同的作用.下面将对NAL Unit中的数据进行 ...

  5. maps.reg

    ^/(.*\.miaopai.com/stream/.*\.mp4\?.*) http://$1 ^/([[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{ ...

  6. 浅谈ES6

    ECMAScript6.0(简称ES6)是javaScript语言的下一代标准,已经在2015年6月正式发布了.它的目标,使得javaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言 ...

  7. 不干胶打印机 www.bgjdyj.com

    不干胶打印机如何保养 不干胶打印机专卖网根据多年的维修经验总结了以下几种保养不干胶打印机的方法: 1.不干胶打印机打印机标签纸不能搁置太长时间,第一容易起静电.第二容易起灰尘2.不干胶打印机的打印头最 ...

  8. 基于线程池的线程管理(BlockingQueue生产者消费者方式)实例

    1.线程池管理类: public class ThreadPoolManager { private static ThreadPoolManager instance = new ThreadPoo ...

  9. CF798E. Mike and code of a permutation [拓扑排序 线段树]

    CF798E. Mike and code of a permutation 题意: 排列p,编码了一个序列a.对于每个i,找到第一个\(p_j > p_i\)并且未被标记的j,标记这个j并\( ...

  10. 夏令营讲课内容整理 Day 6 Part 3.

    第三部分主要讲的是倍增思想及其应用. 在Day3的整理中,我简要提到了倍增思想,我们来回顾一下. 倍增是根据已经得到的信息,将考虑的范围扩大一倍,从而加速操作的一种思想,它在变化规则相同的情况下,加速 ...