js事件循环

javascript是单线程

JavaScript的单线程,因为作为浏览器脚本语言,JavaScript的主要用途是增强用户与 Web 站点和 Web 应用程序之间的交互。这决定了它只能是单线程,否则会带来很复杂的并发问题。但是为了提高网页性能,往往js中都存在着大量的异步操作以解决js同步操作时可能会出现的浏览器的阻塞现象。

异步的必要性 

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。这时对CPU的性能消耗就比较大,同时也会出现浏览器的阻塞现象。所以在js中,主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。所以就形成了javascript的event loop。

通常,在大多数浏览器中,每个浏览器都有一个事件循环,以使每个进程隔离,并避免web页面具有无限循环或繁重的处理来阻塞整个浏览器。

一个 event loop在初始化的时候 他的task队列是空的,并且每一个event loop 都有 a microtask checkpoint flag 也就是类似于现在整个队列中 是否有可以执行的 task的标志. 而这个标志也默认为 false。

一、js的执行同步事件队列

事件循环不断检查调用堆栈以查看是否存在需要运行的任何函数。它会将它找到的任何函数调用添加到调用堆栈并按顺序执行每个调用。

const fn1= () => console.log(‘one’);
const fn2= () => console.log(‘two‘);
const fn3= () =>{
console.log(‘three‘);
fn1();
fn2();
};
fn3();
//输出结果:three,one,two

二、js异步操作

1、dom操作绑定事件

主线程运行的时候,栈中的代码调用各种外部API,它们在"任务队列"中加入各种事件。只要栈中的代码执行完毕,主线程就会去读取"任务队列",依次执行那些事件所对应的回调函数。执行栈中的代码(同步任务),总是在读取"任务队列"(异步任务)之前执行

window.onload=function(){
console.log(‘onloadwindow‘)
};
const fn1= () => console.log(‘one‘);
const fn2= () => console.log(‘two‘);
const fn3= () =>{
console.log(‘three‘);
fn1();
fn2();
};
fn3();
//输出结果:three,one,two,onloadwindow

2、setTimeout
setTimtout是异步事件,js队列执行时,会将处于等待中的任务存储在待执行任务的队列中,当主线程的空闲下来,再去执行存储在任务队列中的任务;

const fn1= () => console.log(‘one‘);
const fn2= () => console.log(‘two‘);
const fn3 = () =>{
console.log(‘three‘);
setTimeout(()=>{
fn1();
},1000);
fn2();
};
fn3();
//输出结果:three,two,one

当设置setTimeout时间间隔为0时,或者中间间隔其他js同步操作时,输出结果都是一样的;因为异步操作会被挂起在任务队列中,当主线程任务执行完毕之后空闲下来,会从任务队列中取出执行。

3、es7 async函数

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。

async 函数中可能会有 await 表达式,async 函数执行时,如果遇到 await 就会先暂停执行 ,等到触发的异步操作完成后,恢复 async 函数的执行并返回解析值。

await 关键字仅在 async function 中有效。如果在 async function 函数体外使用 await ,你只会得到一个语法错误。

function testAwait(){
   return new Promise((resolve) => {
       setTimeout(function(){
          console.log("testAwait");
          resolve();
       }, 1000);
   });
}
async function helloAsync(){
  await testAwait();
  console.log("helloAsync");
 }
helloAsync();
//输出结果:testAwait,helloAsync

补充一下:

Promise对象

Promise 是一个对象,从它可以获取异步操作的消息。

Promise 异步操作有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。除了异步操作的结果,任何其他操作都无法改变这个状态。

Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。只要处于 fulfilled 和 rejected ,状态就不会再变了即 resolved(已定型)。

var promise = new Promise(function(resolve, reject) {
// 异步处理
// 处理结束后、调用resolve 或 reject
});

promise.then() 是 promise 最为常用的方法。then 方法接收两个函数作为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。

原文地址:https://www.cnblogs.com/layaling/p/10608619.html

时间: 2024-08-02 14:47:40

js事件循环的相关文章

js事件循环机制辨析

?对于新接触js语言的人来说,最令人困惑的大概就是事件循环机制了.最开始这也困惑了我好久,花了我几个月时间通过书本,打代码,查阅资料不停地渐进地理解他.接下来我想要和大家分享一下,虽然可能有些许错误的地方,希望大家不吝赐教,感谢感谢. ?这是所涉及的知识点: 观察者模式 js的事件循环机制 js事件循环机制优缺点及与多线程的比较 观察者模式 ?js的事件循环机制是基于观察者模式的,而跟观察者模式相对应的是轮询,我们先来说说轮询的原理. ?我们将轮询映射在现实世界中即为:B不停到A的房间观察房间里

node.js事件循环 event loop

Nodejs事件循环 (event loop) node.js 事件循环的概念 当node.js 启动的时候会初始化eventloop ,每一个evnet loop 都会包含如下6个循环阶段,node.js 事件循环和浏览器事件循环完全不一样. 官网文档:https://nodejs.org/zh-cn/docs/guides/event-loop-timers-and-nexttick/ timers pending callbacks (I/O callbakcs) idle, prepar

Node.js 事件循环

原文:https://github.com/nodejs/node/blob/master/doc/topics/event-loop-timers-and-nexttick.md 什么是事件循环(Event Loop) 事件循环能让 Node.js 执行非阻塞 I/O 操作 -- 尽管JavaScript事实上是单线程的 -- 通过在可能的情况下把操作交给操作系统内核来实现. 由于大多数现代系统内核是多线程的,内核可以处理后台执行的多个操作.当其中一个操作完成的时候,内核告诉 Node.js,

03 js事件循环

1. js里重要的是事件循环. 参考:https://nodejs.org/en/docs/guides/ 中文版:https://github.com/nodejs/nodejs.org/tree/master/locale/zh-cn/docs/guides 写的好的:https://segmentfault.com/a/1190000013861128 好吧,班门弄斧,我简单介绍下,node事件循环,就是不停地去清空任务队列,这里有 微任务,宏任务之分. 微任务: process.next

js事件循环实例解析

js执行顺序分析 console.log(1) setTimeout(()=>{ console.log(2) },2000) setTimeout(()=>{ console.log(3) Promise.resolve().then(()=>{ console.log(4) }) setTimeout(()=>{ console.log(5) },3000) },1000) new Promise((resolve,reject)=>{ console.log(6) re

nodejs 事件循环

Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现. Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数. 事件驱动程序 Node.js 使用事件驱动模型,当web

nodejs基础 -- 事件循环

Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现. Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数. 事件驱动程序 Node.js 使用事件驱动模型,当web

深入理解 JavaScript 事件循环(一)— event loop

引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式,其实他们中有着很大的差别,要完全理解异步,就需要了解 JS 的运行核心——事件循环(event loop).在之前我对事件循环的认识也是一知半解的,直到我看了 Philip Roberts 的演讲 What the heck is the event loop anyway?,我才对事件循环有了一

理解 node.js 的事件循环

node.js 的第一个基本观点是,I/O 操作是昂贵的: 目前的编程技术最大的浪费来自等待 I/O 操作的完成.有几种方法可以解决这些对性能的影响(来自Sam Rushing): 同步:依次处理单个请求. 优点:简单. 缺点:任何一个请求都会阻塞其余请求. 创建新进程:为每个请求创建一个进程处理 优点:容易. 缺点:扩展性不好,数百个连接意味着数百个进程.fork()是 Unix 程序员的锤子.因为它很有用,所有的问题都像是钉子.但这通常是多余的. 线程:为每个请求创建一个线程处理. 优点:容