2 任务队列 在整个事件循环过程中,有四个队列(实际的数据结构不是队列)是在 libuv 的事件循环中进行的,还有两个队列是在 nodejs 中执行的分别是 promise 队列 和 nextTick...在 NodeJS 中不止一个队列,不同类型的事件在它们自己的队列中入队。在处理完一个阶段后,移向下一个阶段之前,事件循环将会处理两个中间队列,直到两个中间队列为空。...这个是在 nodejs 中特有的。 Microtasks 微队列 Promise :存放 promise 的回调函数。...中间队列的执行特点: 首先要明白两个中间队列并非在 libuv 中被执行,它们都是在 nodejs 层执行的,在 libuv 层处理每一个阶段的任务之后,会和 node 层进行通讯,那么会优先处理两个队列中的任务...无论是 nextTick 的任务,还是 promise 中的任务, 两个任务中的代码会阻塞事件循环的有序进行,导致 I/O 饿死的情况发生,所以需要谨慎处理两个任务中的逻辑。
同步异步和阻塞非阻塞 在讨论nodejs的异步编程之前,让我们来讨论一个比较容易混淆的概念,那就是同步,异步,阻塞和非阻塞。...所谓阻塞和非阻塞是指进程或者线程在进行操作或者数据读写的时候,是否需要等待,在等待的过程中能否进行其他的操作。...回调函数的错误处理 在nodejs中怎么处理回调的错误信息呢?...nodejs采用了一个非常巧妙的办法,在nodejs中,任何回调函数中的第一个参数为错误对象,我们可以通过判断这个错误对象的存在与否,来进行相应的错误处理。...Promise的特点 Promise有两个特点: 对象的状态不受外界影响。
new promise时, 需要传递一个executor()执行器——这个函数在new Promise 时立即执行;Promise 的 executor 函数有两个参数,一个是 resolve,一个是...,p3Res]有了all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据Promise.race(iterable),传入的promises数组中一个promose resolve 或者...如果可迭代对象中没有一个 promise 完成(即所有的 promises 都失败/拒绝),就返回一个拒绝的 promise。目前没有几个浏览器支持。...否则,在catch内捕获注意:一个promise,只有第一个reject操作失败结果,非Promise链中reject不会影响后面.then()的执行,并且如果reject和catch两种方式同时使用的话...我们同样使用try/catch结构,但是在promises的情况下,try/catch难以处理在JSON.parse过程中的问题,原因是这个错误发生在Promise内部。
在73以下版本中 首先,传递给 await 的值被包裹在一个 Promise 中。...然后先执行打印promise1,此时then的回调函数返回undefinde,此时又有then的链式调用,又放入微任务队列中,再次打印promise2。...再回到await的位置执行返回的 Promise 的 resolve 函数,这又会把 resolve 丢到微任务队列中,打印async1 end。...poll: 最重要的阶段,执行pending callback,在适当的情况下会阻塞在这个阶段。...poll 该poll阶段有两个主要功能: 执行I/O回调。 处理轮询队列中的事件。
因此会打印出这样的结果: timer1 timer2 promise1 promise2 4.nodejs 和 浏览器关于eventLoop的主要区别 两者最主要的区别在于浏览器中的微任务是在每个相应的宏任务中执行的...,而nodejs中的微任务是在不同阶段之间执行的。...在浏览器端,只有一种 I/O,那就是利用 Ajax 发送网络请求,然后读取返回的内容,这属于网络I/O。回到 nodejs 中,其实这种的 I/O 的场景就更加广泛了,主要分为两种: 文件 I/O。...那如果换成非阻塞I/O,调用返回后我们的 nodejs 应用程序可以完成其他的事情,而操作系统同时也在进行 I/O。...但是这段程度还是存在一些问题: 首先 then 中的两个参数不传的情况并没有处理, 假如 then 中的回调执行后返回的结果(也就是上面的x)是一个 Promise, 直接给 resolve 了,这是我们不希望看到的
相关概念浏览器我们都知道,是典型的多进程模型,但是JavaScript的运行时却是单线程的架构,我们来从浏览器出发看看具体JavaScript的运行时在浏览器中处于什么位置。...Promise中的setTimeout延时也是0,会作为宏任务放入到事件处理线程的宏任务队列中,注意,此时还未进入JS引擎线程,且事件处理线程已有两个宏任务正在等待。...由于Promise中的唯一一个resolve是在setTimeout中,所以当前loop中Promise无法执行完,只能保持pending状态。...继续执行遇到第二个await,同理正常执行testAsync函数输出步骤2,在return之后注册微任务并挂起,交出线程控制权,此时微任务队列仍有两个任务:主代码块的Promise.then和第二个await...NodeJS中的运行机制 Node 中的 Event Loop 和浏览器中的是完全不相同的东西。
nodejs是单线程执行的,同时它又是基于事件驱动的非阻塞IO编程模型。这就使得我们不用等待异步操作结果返回,就可以继续往下执行代码。当异步事件触发之后,就会通知主线程,主线程执行相应事件的回调。...undefined在nodejs里,胶水代码的主要作用是把nodejs底层实现的C/C++库暴露给js环境。...undefinedlibuv:是用C语言实现的一套异步功能库,nodejs高效的异步编程模型很大程度上归功于libuv的实现,而libuv则是我们今天重点要分析的。...,很明显,nodejs的网络I/O、文件I/O、DNS操作、还有一些用户代码都是在 libuv 工作的。...既然谈到了异步,那么我们首先归纳下nodejs里的异步事件:非I/O:定时器(setTimeout,setInterval)microtask(promise)process.nextTicksetImmediateDNS.lookupI
简介 ES6中除了上篇文章讲过的语法新特性和一些新的API之外,还有两个非常重要的新特性就是Promise和Generator,今天我们将会详细讲解一下这两个新特性。...Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。...要记住yield本身是没有返回值的。 我们需要调用generator的next方法,将异步执行的结果传进去。这就是我们在request方法中做的事情。...比如nodejs中的: fs.readFile(filename,[encoding],[callback(err,data)]) readFile接收3个参数,其中encoding是可选的。...我们就以两个参数为例。 一般来说,我们这样调用: fs.readFile(fileA,callback); 那么有没有办法将其改写成为单个参数的function的级联调用呢?
Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。...Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。...resolve 函数的作用是,将 Promise 对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject...函数的作用是,将 Promise 对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。 ...实例,当这个数组中的 Promise 实例全部返回时,方法执行结束 race(数组): 接收一个数组,每个数组元素都是一个 Promise 实例,当这个数组中的 Promise 实例有一个返回时,方法执行结束
nodejs是单线程执行的,同时它又是基于事件驱动的非阻塞IO编程模型。这就使得我们不用等待异步操作结果返回,就可以继续往下执行代码。当异步事件触发之后,就会通知主线程,主线程执行相应事件的回调。...undefined在nodejs里,胶水代码的主要作用是把nodejs底层实现的C/C++库暴露给js环境。...undefinedlibuv:是用C语言实现的一套异步功能库,nodejs高效的异步编程模型很大程度上归功于libuv的实现,而libuv则是我们今天重点要分析的。...既然谈到了异步,那么我们首先归纳下nodejs里的异步事件:非I/O:定时器(setTimeout,setInterval)microtask(promise)process.nextTicksetImmediateDNS.lookupI...undefined2、其次呢,在poll阶段,timeout时间未到的时候,如果有事件返回,就执行该事件注册的回调函数。timeout超时时间到了,则退出poll阶段,执行下一个阶段。
IE 事件模型,在该事件模型中,一次事件共有两个过程,事件处理阶段和事件冒泡阶段。事件处理阶段会首先执行目标元素绑定的监听事件。...这种模型通过attachEvent 来添加监听函数,可以添加多个监听函数,会按顺序依次执行。DOM2 级事件模型,在该事件模型中,一次事件共有三个过程,第一个过程是事件捕获阶段。...后面两个阶段和 IE 事件模型的两个阶段相同。这种事件模型,事件绑定的函数是addEventListener,其中第三个参数可以指定事件是否在捕获阶段执行。...基本特性1、Promise有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)2、Promise对象接受一个回调函数作为参数, 该回调函数接受两个参数,分别是成功时的回调...移动端适配主要有两个维度:适配不同像素密度, 针对不同的像素密度,使用 CSS 媒体查询,选择不同精度的图片,以保证图片不会失真;适配不同屏幕大小, 由于不同的屏幕有着不同的逻辑像素大小,所以如果直接使用
)Promise基本特性1、Promise有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)2、Promise对象接受一个回调函数作为参数, 该回调函数接受两个参数...3、then方法返回一个新的Promise实例,并接收两个参数onResolved(fulfilled状态的回调);onRejected(rejected状态的回调,该参数可选)4、catch方法返回一个新的...下面这些操作会导致回流:页面的首次渲染浏览器的窗口大小发生变化元素的内容发生变化元素的尺寸或者位置发生变化元素的字体大小发生变化激活CSS伪类查询某些属性或者调用某些方法添加或者删除可见的DOM元素在触发回流...,但是不会影响其在文档流中的位置时,浏览器就会对元素进行重新绘制,这个过程就是重绘。...CSS3中的盒模型有以下两种:标准盒模型、IE盒模型盒模型都是由四个部分组成的,分别是margin、border、padding和content标准盒模型和IE盒模型的区别在于设置width和height
timer2 的回调函数进入主栈并执行,打印 timer2 ② 微任务:微任务队列中无任务,第二轮事件循环结束 第三轮事件循环: ① 宏任务:宏任务队列中依次有 timer3 和 timer1 这两个定时器的回调函数...timer1 的回调函数进入主栈并执行,打印 timer1 ② 微任务:微任务队列中无任务,第四轮事件循环结束 其二 之后又看到这么一段代码(Nodejs): let fs = require('fs'...中的执行器,进而执行 readFile 函数,由于 resolve 是位于异步回调函数中(尚未执行),所以这里返回的是一个处于 pending 状态的 Promise;此外,每一次迭代也会将 then...在回调执行前,我们是拿不到文件内容的。 readAll 执行完毕,返回到主栈,第一次打印 4。.....of 里面的代码就是彻底的同步代码了,在每一次打印 4 之后,promise 也是紧跟着打印出来的,经过前面的分析可以知道,这个时候的 promise 还处于 pending 状态,所以打印结果自然会是
如你所见,在 IO 和计时器队列中,所有与异步操作有关的内容都被移交给了异步函数。 但是 promise 不同。...在 promise 中,初始变量存储在 JavaScript 内存中(你可能已经注意到了)。 异步操作完成后,Node.js 会将函数(附加到 Promise)放在微任务队列中。...同时它用得到的结果来更新 JavaScript 内存中的变量,以使该函数不与 一起运行。...你肯sing不希望在处理 promise 函数之前在 close 事件中执行回调函数。当服务器已经关闭时,promise 函数会做些什么呢?...# 返回 "last line" "setTimeout" 当事件循环继续执行队列中的回调函数时,promise 操作完成并被添加到微任务队列中: // 队列 Timer = [];
Js是单线程的,其引入了同步阻塞与异步非阻塞的执行模式,在Js异步模式中维护了一个Event Loop,Event Loop是一个执行模型,在不同的地方有不同的实现,浏览器和NodeJS基于不同的技术实现了各自的...浏览器的Event Loop是在HTML5的规范中明确定义,NodeJS的Event Loop是基于libuv实现的。...在测试的过程中发现了一个很有意思的现象,在上述例子中的加入两个按钮,在点击updateMsg按钮的结果是3 2 1,点击updateMsgTest按钮的运行结果是2 3 1。 Copy <!...pending) { pending = true; timerFunc(); } if (!cb && typeof Promise !...(2))语句的挂载,当执行微任务队列中的任务时,首先会执行第一个挂载到Promise的任务,此时这个任务是运行执行队列,这个队列中有两个方法,首先会运行flushSchedulerQueue方法去触发组件的
文章会从以下方面: ✨ 并发模型 ✨ 浏览器中的 EventLoop ✨ NodeJs 中的 EventLoop ✨ 浏览器和 NodeJs 中 EventLoop 的差距 本文会从以上四个方面带你探索不同运行环境下的...并发模型 在 JavaScript 中我们听到最多的词可能就是所谓的“单线程”,所以导致了在 JS 中所谓的异步并行模型和许多后台语言是不同的。...注意,此时我们会进入 poll 轮询阶段,此时 poll 阶段并不存在任何 IO 相关回调,返回在轮询阶段他会检测到我们代码中存在 setImmediate ,并且 setImmediate 的 callback...所以在主调用栈中调用这两个 Api 时会根据 Timeout 以及代码执行时间,造成先输出 immediate ,之后在执行 timers。...在 EventLoop 中必不可少的两个概念:Macro(宏任务)、Micro(微任务)。
await,但是在写下这篇文章之前,却不知道Promise背后发生了些什么,我一直以为的逻辑是先等待Promise构造方法中的异步函数完成后,再调用then方法执行其中的函数。...IPromise { status: STATUS // 表明当前Promise的状态,不可逆,在进行then添加方法时,会根据这个状态做出不同的处理 value: any // 异步函数执行成功后返回的值...} 改进后的then方法改进了两个地方 判断通过then方法注册事件时Promise的状态,一个Promise的状态应该是确定的不可逆的,即只能从PENDING状态转换为fulfilled或者reject...,当调用then方法注册事件时,如果此时这个Promise已经不是PENDING了,将会根据现在的Promise类型执行then注册的函数 每次调用then方法进行函数注册的时候都会返回一个新的Promise...接着我们考虑了注册的onFulfilled函数,如果这个函数返回的是一个Promise,则继续向它注册事件 小结 Promise本质就是一个发布订阅模式,异步函数是整个模型的驱动器,完成时调用resolve
后来出现的Generator函数以及Async函数也是以Promise为基础的进一步封装,可见Promise在异步编程中的重要性。...then方法必须返回一个新的promise,记作promise2,这也就保证了then方法可以在同一个promise上多次调用。...好了,有了解决办法,我们就把代码进一步完善: class Promise { // 定义Promise状态变量,初始值为pending status = 'pending'; // 因为在then...Promise是我司前端开发职位,nodejs开发职位,全栈开发职位,必问的一个知识点,主要问题会分布在Promise介绍、基础使用方法以及深层次的理解三个方面,问题一般在3-5个,根据面试者回答情况会适当增减...3、Promise.then在Event Loop中的执行顺序。
领取专属 10元无门槛券
手把手带您无忧上云