繁体   English   中英

NodeJS事件循环多个请求

[英]NodeJS Event Loop Multiple Request

我对以下代码有疑问(来源: https//blog.risingstack.com/node-js-at-scale-understanding-node-js-event-loop/ ):

'use strict'  
const express = require('express')  
const superagent = require('superagent')  
const app = express()

app.get('/', sendWeatherOfRandomCity)

function sendWeatherOfRandomCity (request, response) {  
  getWeatherOfRandomCity(request, response)
  sayHi()
}

const CITIES = [  
  'london',
  'newyork',
  'paris',
  'budapest',
  'warsaw',
  'rome',
  'madrid',
  'moscow',
  'beijing',
  'capetown',
]

function getWeatherOfRandomCity (request, response) {  
  const city = CITIES[Math.floor(Math.random() * CITIES.length)]
  superagent.get(`wttr.in/${city}`)
    .end((err, res) => {
      if (err) {
        console.log('O snap')
        return response.status(500).send('There was an error getting the weather, try looking out the window')
      }
      const responseText = res.text
      response.send(responseText)
      console.log('Got the weather')
    })

  console.log('Fetching the weather, please be patient')
}

function sayHi () {  
  console.log('Hi')
}

app.listen(3000);

我有这些问题:

  1. 当getWeatherOfRandomCity方法中的superagent.get( wttr.in/${city} )http://wttr.in/sf发出Web请求时,该请求将被置于任务队列而不是主要调用堆栈正确吗?
    1. 如果主调用堆栈上有方法(即主调用堆栈不为空),则结束事件附加到superagent.get( wttr.in/${city} ).end(...) (即被推到任务队列)直到主调用堆栈为空是否正确才会被调用? 换句话说,在事件循环的每个刻度上,它将从任务队列中获取一个项目?
    2. 假设有两个对localhost:3000/请求localhost:3000/一个接一个地进来。 第一个请求将推送堆栈上的sendWeatherOfRandomCity,堆栈上的getWeatherOfRandomCity,然后将web请求superagent.get( wttr.in/${city} ).end(...)放在后台队列中,然后console.log('Fetching the weather, please be patient') ,然后sendWeatherOfRandomCity将从堆栈弹出,最后sayHi()将被推入堆栈,它将打印“Hi”并弹出堆栈,最后附加到superagent.get( wttr.in/${city} ).end(...)结束事件将从任务队列中调用,因为主调用堆栈将为空。 现在,当第二个请求到来时,它会将所有与第一个请求相同的内容推送到主调用堆栈,但是第一个请求(仍然在任务队列中)的结束处理程序将首先运行,或者将内容推送到主调用第二个Web请求的堆栈会先运行吗?

当您发出http请求时,libuv会发现您正在尝试发出网络请求。 libuv和node都没有任何代码来处理网络请求涉及的所有这些操作。 而是libuv将请求委托给底层操作系统。

它实际上是内核,它是我们操作系统的重要组成部分,可以完成真正的网络请求。 Libuv用于发出请求,然后它只是等待操作系统发出一个信号,表明某些响应已经回到请求。 因此,由于Libuv将完成的工作委托给操作系统,操作系统本身决定是否制造新的威胁。 或者只是一般如何处理发出请求的整个过程。 每个不同的操作系统都有不同的方法来处理这个:在linux上它是epoll,在mac os中它被称为kqueue,在windows中它被称为GetQueuedCompletionStatusEx。

事件循环中有6个阶段,其中一个是i / o轮询。 每个阶段都优先于其他阶段。 1号总是定时器。 当时间到了,(或事件完成)定时器的回调将被调用到事件队列,定时器功能也将移动到事件队列。 然后事件循环将检查调用堆栈是否可用。 调用堆栈是函数执行的地方。 你可以一次做一件事,调用堆栈强制我们只能在调用堆栈的顶部有一个函数,这是我们正在做的事情。在JAVASCRIPT RUNTIME中无法同时执行两件事。

如果调用堆栈为空意味着删除了main()函数,则事件循环将推送定时器函数调用堆栈并执行您的函数。 在主函数完成之前,所有Async回调都不会运行。

因此,当I / O轮询阶段处理传入数据和连接时,使用相同的路径定时器函数如何跟随,将执行处理提取的函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM