Node.js 由 Baixo dos Panos #1 - Conhecendo nossas ferramentas

2025-05-28

Node.js 由 Baixo dos Panos #1 - Conhecendo nossas ferramentas

原始翻译

最近,我们与巴西主要会议(The Conf)进行了交谈。这是一系列针对特殊情况的艺术。

会议的目标是用英语进行会议,目前为止,世界各地的受益者都将受益于未来的在线支持。 E não apenas nós, brasileiros que falamos Português.

这条消息是我们继续下去的,它是我们的目标,它是我们前进的方向,是我们前进的方向,是我们前进的方向。决定如何使用 Node.js、JavaScript 和 Node.js 的生态、功能。我是一个主要的节目主持人,在美国,作为coisas,mas ninguém nunca para para pensar como elas funcionam ou o que elas fazem。

实际上,没有任何东西是“aceitável”的,但删除库是必要的,因为它是书本的必要条件,并且主要是书本处理程序的结构,以便在大会上进行相关的编写。 No entanto, isso nos tornou preguiçosos, usar coisas sem saber nada sobre elas criou uma atmosfera onde todos só sabem o suficiente e só leem o suficiente para criar o que precisam, e esquecem sobre todos os conceitos que vem junto com aquilo.最后,请复制 Stack Overflow 上的内容,一切都很简单。

总之,我们决定 Node.js 的内部结构,并与 Node.js 的生态系统一起工作。

这是一些特别的主题,包括在 Minha 巴勒斯坦地区进行的编译和研究。您不能将所有帖子作为参考书目,也可以作为参考书目。在此过程中,您将在不同的情况下继续进行下去,最后我们将在各个方面进行讨论,最后,您可以将其作为参考和幻灯片。

我相信你很聪明 :D

目标

Node.js 的内部功能,它是 Node eo JavaScript 中的知名人士,它与库中的库、主要功能、功能一起使用。卡波。详细说明如下:

  1. Node.js 是什么
    1. 简史
    2. JS 的简史
    3. Node.js 的组成部分
  2. 嗯,例如 uma chamada de leitura de arquivos
  3. JavaScript
    1. 它如何运作?
      1. 调用堆栈
    2. 记忆分配
  4. Libuv
    1. 什么是 libuv?
    2. 我们知道什么?
    3. 事件循环
    4. 微任务和宏任务
  5. V8
    1. 什么 V8
    2. 概述
      1. 抽象语法树 usando Esprima
    3. 反编译管道
      1. O 完整的代码生成
      2. 曲轴
    4. 新编译管道
      1. 点火
      2. 涡轮风扇
        1. 隐藏类和变量分配
    5. 垃圾收集
  6. 编译优化
    1. 常量折叠
    2. 变化原因分析
    3. 重新物质化
    4. 删除递归
    5. 德弗洛雷斯塔门托
    6. 优化窥视孔
    7. 内联扩展
    8. 内联缓存
    9. 死亡代码消除
    10. 代码块重组
    11. 跳转线程
    12. 蹦床
    13. 消除次表达

Node.js 是什么

Node.js 由 Ryan Dahl(criador 原创)定义,“与 V8 的执行方式相结合,允许在 JavaScript 中执行无服务器”,维基百科定义为“运行时 JavaScript 开源、多平台执行方式”。

Node.js 的本质是运行时,不允许在 JS 中执行操作。没有任何问题,根本不需要 Javascript 来实现没有服务器的服务。 1995 年,Netscape 实现了 Netscape Enterprise Server,但允许在没有服务器的情况下执行 LiveScript(或 JavaScript)。

Node.js 简史

Node.js 于 2009 年首次推出,由 Ryan Dahl 编写,但迟到了 Patrocinado Joyent。目前,运行时的方案是 Apache HTTP Server 的可能性限制 - 网络服务器在当今流行 - 激光雷达可以同时使用。但是,达尔批评了一系列连续的操作,并在整个过程中进行了一系列内部处理或执行不同的操作,而不是同时进行不同的操作。

Node.js 是 JSConf EU 的代表,于 2009 年 11 月 8 日发布。结合了 V8、事件循环 - 最近的脚本 - libuv 和 I/O 下的 uma API。

JavaScript简史

Javascript 和定义的“语言脚本解释”符合特定的 ECMAScript 和 TC39。 Criado 是 1995 年由 Brendan Eich 编写的 Netscape 脚本语言。 JavaScript 是马克·安德森 (Marc Andreessen) 在 HTML 和 Web 设计人员中的“可乐语言”的独特设计,是图像和插件的常用组件,在 Web 页面上没有标记,因此可以直接编写代码。

Brendan Eich 在 Netscape 上实现了一个语言方案,他在 Sun Microsystems 和 Netscape 中开发了一个包含 Java 的 Netscape 框架,并在 Java 中实现了一个语言方案。 Para Defender a idéia do JavaScript contra outras proppostas, Eich escreveu, em 10 dias, um protótipo funcional.

ECMA 的具体规定,是 Netscape 在 ECMA International 中使用 JavaScript 语言的具体规定,是在 Netscape 上实现的导航器实现的基础。 ECMA-262 于 1997 年发布。 ECMAScript-3 于 1999 年发布,是现代 JavaScript 语言的基础语言。 ECMAScript 4 是为了与 Microsoft 合作而不是在 IE 中实现 JavaScript,而不是在 IE 中使用 JavaScript 来替代 JS 和在 .NET 语言中实现服务。

2005 年,作为 comunidades de código aberto 和 desenvolvedores começaram a trabalhar para revolucionar o que poderia ser feito com JavaScript。 Primeiro,在 2005 年,Jesse James Garret 公开了他的 AJAX 技术,并通过 jQuery、Prototype 和 MooTools 的参考书目,使 JavaScript 得到了复兴。 2008 年,我们在 2009 年宣布了 JS novamente 和 ECMAScript 5 的社区。

Node.js 的组成元素

O Node.js 和依赖算法的组合:

  • V8
  • Libuv
  • http解析器
  • c-战神
  • OpenSSL
  • zlib

一个形象的解释是完美的:

摘自 Samer Buna 的 Pluralsight 课程:高级 Node.js

大多数情况下,Node.js 的主要部分是:V8 和 libuv。 O V8 大约包含 70% 的 C++ 和 30% 的 JavaScript,并且包含 C 的 libuv 和完整的 escrita。

例子 - Uma chamada de leitura de bados

Para alcançar nosso objetivo (e ter um roteiro claro do que vamos fazer), começaremos escrevendo um programa simples que lê um arquivo eo imprime na tela。我想说的是,这是一个理想的编程者所希望的,作为我们的目标,我们希望能够实现这一目标。

这是 Node.js 的核心内容。, notará duas 意大利面 原则: libe src.意大利面lib是当今的一个话题,作为当前项目中的功能和模块的定义,请在 JavaScript 中编写。一个srcC++ 结合使用的工具,可以在 Libuv eo V8 中使用,并且可以作为其他模块的工具fs使用httpcrypto

这就是这个简单的程序:

const fs = require('fs')
const path = require('path')
const filePath = path.resolve(`../myDir/myFile.md`)

// Parseamos o buffer em string
function callback (data) {
  return data.toString()
}

// Transformamos a função em uma promise
const readFileAsync = (filePath) => {
  return new Promise((resolve, reject) => {
    fs.readFile(filePath, (err, data) => {
      if (err) return reject(err)
      return resolve(callback(data))
    })
  })
}

(() => {
  readFileAsync(filePath)
    .then(console.log)
    .catch(console.error)
})()
Enter fullscreen mode Exit fullscreen mode

Sim,它存在于util.promisifyeo fs.promises、porém、eu 查询转换器手册或回调函数中,并且是一种承诺,可以实现内部部分的美好愿望。

与某个程序相关的所有示例。这是V8或 JavaScript 的一部分fs.readFile它的功能是通过 Node.js 实现的,并且可以与 C++ 绑定到本地操作系统,无需任何操作,它是一个在 JavaScript 中使用的 API,可以实现绑定。 Aqui está o código fonte completo dessa função especamente (porque o arquivo inteiro tem 1850 linhas, mas está nasreferências):fs.readFile (path, cb)readFile

// https://github.com/nodejs/node/blob/0e03c449e35e4951e9e9c962ff279ec271e62010/lib/fs.js#L46
const binding = internalBinding('fs');
// https://github.com/nodejs/node/blob/0e03c449e35e4951e9e9c962ff279ec271e62010/lib/fs.js#L58
const { FSReqCallback, statValues } = binding;

// https://github.com/nodejs/node/blob/0e03c449e35e4951e9e9c962ff279ec271e62010/lib/fs.js#L283
function readFile(path, options, callback) {
  callback = maybeCallback(callback || options);
  options = getOptions(options, { flag: 'r' });
  if (!ReadFileContext)
    ReadFileContext = require('internal/fs/read_file_context');
  const context = new ReadFileContext(callback, options.encoding);
  context.isUserFd = isFd(path); // File descriptor ownership

  const req = new FSReqCallback();
  req.context = context;
  req.oncomplete = readFileAfterOpen;

  if (context.isUserFd) {
    process.nextTick(function tick() {
      req.oncomplete(null, path);
    });
    return;
  }

  path = getValidatedPath(path);
  binding.open(pathModule.toNamespacedPath(path),
               stringToFlags(options.flag || 'r'),
               0o666,
               req);
}
Enter fullscreen mode Exit fullscreen mode

免责声明:本文档是关于 Github 上的原始链接和提交部分的参考资料,但可能0e03c449e35e4951e9e9c962ff279ec271e62010是最近没有的时刻,因此,本文档始终是关于实现的相关文件。

Vê a linha 5? Temos uma chamada requirepara read_file_context, outro arquivo JS (que também está nasreferências)。没有最终的código fonte para fs.readFile、 temos uma chamada para binding.open、 que é uma chamada C++ para abrir um 文件描述符、 passando o caminho、 os sinalizadores fopendo C++, as Permissões do modo de arquivo no formatato Octal ( 0o éo formatato Octal no ES6 ) e, por último, a variável req, que é ocallback assíncrono que receberá nossa resposta。

Junto com 是这样的,它是internalBindingC++ 内部私人绑定的加载程序,但它是 C++ 中常用的解决方案NativeModule.require。 E é aqui que dependentemos MUITO do V8

基本的,没有código acima,estamos dando um requireem um binding fscom internalBinding('fs'),que chama e carrega o arquivo src/node_file.cc(porque todo esse arquivo está no namespace fs)que contém todas em C++ para as funções FSReqCallbacke statValues

一个回调函数FSReqCallback,用于传递所有chamamos fs.readFile(quando usamos fs.readFileSync,存在外部函数chamada FSReqWrapSyncque é definida aqui)和todos os seus métodos和implementações estão definidos aqui和expostos como绑定aqui

// https://github.com/nodejs/node/blob/0e03c449e35e4951e9e9c962ff279ec271e62010/src/node_file.cc

FileHandleReadWrap::FileHandleReadWrap(FileHandle* handle, Local<Object> obj)
  : ReqWrap(handle->env(), obj, AsyncWrap::PROVIDER_FSREQCALLBACK),
    file_handle_(handle) {}

void FSReqCallback::Reject(Local<Value> reject) {
  MakeCallback(env()->oncomplete_string(), 1, &reject);
}

void FSReqCallback::ResolveStat(const uv_stat_t* stat) {
  Resolve(FillGlobalStatsArray(env(), use_bigint(), stat));
}

void FSReqCallback::Resolve(Local<Value> value) {
  Local<Value> argv[2] {
    Null(env()->isolate()),
    value
  };
  MakeCallback(env()->oncomplete_string(),
               value->IsUndefined() ? 1 : arraysize(argv),
               argv);
}

void FSReqCallback::SetReturnValue(const FunctionCallbackInfo<Value>& args) {
  args.GetReturnValue().SetUndefined();
}

void NewFSReqCallback(const FunctionCallbackInfo<Value>& args) {
  CHECK(args.IsConstructCall());
  Environment* env = Environment::GetCurrent(args);
  new FSReqCallback(env, args.This(), args[0]->IsTrue());
}

// Create FunctionTemplate for FSReqCallback
Local<FunctionTemplate> fst = env->NewFunctionTemplate(NewFSReqCallback);
fst->InstanceTemplate()->SetInternalFieldCount(1);
fst->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<String> wrapString =
    FIXED_ONE_BYTE_STRING(isolate, "FSReqCallback");
fst->SetClassName(wrapString);
target
    ->Set(context, wrapString,
          fst->GetFunction(env->context()).ToLocalChecked())
    .Check();
Enter fullscreen mode Exit fullscreen mode

最后,构造器的定义是:Local<FunctionTemplate> fst = env->NewFunctionTemplate(NewFSReqCallback)。 Isso basicamente diz que, quando chamamos new FSReqCallback (), a função NewFSReqCallbackserá chamada. Agora veja como a propriedade contextaparece na parte target->Set(context, wrapString, fst->GetFunction)e também como o oncompletetambém é definido e usado no ::Rejecte ::Resolve.

重要的是,它req是一个变化的结果new ReadFileContext,是context一个参考和定义req.context。这是一个代表reqC++ 绑定回调函数的变量,它可以配置回调函数和FSReqCallback()事件的上下文oncomplete

结论

没有任何时刻,não vimos muito。没有entanto,em artigos postes,iremos abordar cada vez mais como as coisas realmente funcionam e como podemos usar nossa função para entend melhor nossas ferramentas!

您可以继续阅读我的博客并添加新闻通讯来接收最新消息!

文章来源:https://dev.to/_staticvoid/node-js-por-baixo-dos-panos-1-conhecendo-nossas-ferramentas-34b6
PREV
Node.js 底层原理 #1 - 了解我们的工具
NEXT
多睡觉,多写代码