[node] Node.js的内置模块

[node] Node.js的内置模块

  • Domain 模块
    • 使用方式
    • 方法概览
    • 属性
    • 示例
  • DNS 模块
    • 使用方式
    • 方法概览
      • rrtypes
    • 错误码
    • 示例
  • Net 模块
    • 使用方式
    • 方法概览
    • net.Server
      • 方法
      • 事件
    • net.Socket
      • net.Socket 事件
      • 属性
      • 方法
    • 示例
  • os
    • 使用方式
    • 方法概览
    • 示例
  • util
    • 使用方式
    • 常用方法
      • util.callbackify
      • ~~util.inherits~~
      • util.inspect
      • util.isArray
      • util.isRegExp
      • util.isDate
  • 如何调试

Domain 模块

Node.js Domain(域) 简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的异常。

使用方式

var domain = require("domain")

domain模块,把处理多个不同的IO的操作作为一个组。注册事件和回调到domain,当发生一个错误事件或抛出一个错误时,domain对象会被通知,不会丢失上下文环境,也不导致程序错误立即退出,与process.on(‘uncaughtException’)不同。

Domain 模块可分为隐式绑定和显式绑定:

  • 隐式绑定: 把在domain上下文中定义的变量,自动绑定到domain对象
  • 显式绑定: 把不是在domain上下文中定义的变量,以代码的方式绑定到domain对象

方法概览

方法 描述
domain.run(function) 在域的上下文运行提供的函数,隐式的绑定了所有的事件分发器,计时器和底层请求
domain.add(emitter) 显式的增加事件
domain.remove(emitter) 删除事件
domain.bind(callback) 返回的函数是一个对于所提供的回调函数的包装函数。当调用这个返回的函数时,所有被抛出的错误都会被导向到这个域的 error 事件
domain.intercept(callback) 和 domain.bind(callback) 类似。除了捕捉被抛出的错误外,它还会拦截 Error 对象作为参数传递到这个函数
domain.enter() 进入一个异步调用的上下文,绑定到domain。
domain.exit() 退出当前的domain,切换到不同的链的异步调用的上下文中。对应domain.enter()
domain.dispose() 释放一个domain对象,让node进程回收这部分资源
domain.create() 返回一个domain对象

属性

属性 描述
domain.members 已加入domain对象的域定时器和事件发射器的数组。

示例

main.js

var EventEmitter = require("events").EventEmitter;
var domain = require("domain");

var emitter1 = new EventEmitter();
// 创建域
var domain1 = domain.create();
domain1.on("error", function (err) {
  console.log("domain1 处理这个错误 (" + err.message + ")");
});
// 显式绑定
domain1.add(emitter1);
emitter1.on("error", function (err) {
  console.log("监听器处理此错误 (" + err.message + ")");
});
emitter1.emit("error", new Error("通过监听器来处理"));
emitter1.removeAllListeners("error");
emitter1.emit("error", new Error("通过 domain1 处理"));
var domain2 = domain.create();
domain2.on("error", function (err) {
  console.log("domain2 处理这个错误 (" + err.message + ")");
});
// 隐式绑定
domain2.run(function () {
  var emitter2 = new EventEmitter();
  emitter2.emit("error", new Error("通过 domain2 处理"));
});
domain1.remove(emitter1);
emitter1.emit("error", new Error("转换为异常,系统将崩溃!"));
//终端执行 node main.js
//输出
// 监听器处理此错误 (通过监听器来处理)
// domain1 处理这个错误 (通过 domain1 处理)
// domain2 处理这个错误 (通过 domain2 处理)
// node:events:491
//       throw er; // Unhandled 'error' event
//       ^

// Error: 转换为异常,系统将崩溃!
//     at Object. (D:\test\temp1.cjs:28:24)
//     at Module._compile (node:internal/modules/cjs/loader:1254:14)
//     at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
//     at Module.load (node:internal/modules/cjs/loader:1117:32)
//     at Module._load (node:internal/modules/cjs/loader:958:12)
//     at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
//     at node:internal/main/run_main_module:23:47

DNS 模块

Node.js DNS 模块用于解析域名

使用方式

var dns = require("dns")

方法概览

方法 描述
dns.lookup(hostname[, options], callback) 将域名(比如 xxx.com)解析为第一条找到的记录 A (IPV4)或 AAAA(IPV6)。options可以是一个对象或整数。如果没有提供 options,IP v4 和 v6 地址都可以。如果 options 是整数,则必须是 4 或 6。
dns.lookupService(address, port, callback) 使用 getnameinfo 解析传入的地址和端口为域名和服务。
dns.resolve(hostname[, rrtype], callback) 将一个域名(如 xxxx.com)解析为一个 rrtype 指定记录类型的数组
dns.resolve4(hostname, callback) 和 dns.resolve() 类似, 仅能查询 IPv4 (A 记录)。 addresses IPv4 地址数组 (比如,[74.125.79.104, 74.125.79.105])
dns.resolve6(hostname, callback) 和 dns.resolve4() 类似, 仅能查询 IPv6( AAAA 查询)
dns.resolveMx(hostname, callback) 和 dns.resolve() 类似, 仅能查询邮件交换(MX 记录)
dns.resolveTxt(hostname, callback) 和 dns.resolve() 类似, 仅能进行文本查询 (TXT 记录)。 addresses 是 2-d 文本记录数组。(比如,[ ['v=spf1 ip4:0.0.0.0 ', ‘~all’ ] ])。 每个子数组包含一条记录的 TXT 块。根据情况可以连接在一起,也可单独使用
dns.resolveSrv(hostname, callback)) 和 dns.resolve() 类似, 仅能进行服务记录查询 (SRV 记录)。 addresses 是 hostname可用的 SRV 记录数组。 SRV 记录属性有优先级(priority),权重(weight), 端口(port), 和名字(name) (比如,[{‘priority’: 10, ‘weight’: 5, ‘port’: 21223, ‘name’: ‘service.example.com’}, …])
dns.resolveSoa(hostname, callback) 和 dns.resolve() 类似, 仅能查询权威记录(SOA 记录)
dns.resolveNs(hostname, callback) 和 dns.resolve() 类似, 仅能进行域名服务器记录查询(NS 记录)。 addresses 是域名服务器记录数组(hostname 可以使用) (比如, [‘ns1.example.com’, ‘ns2.example.com’])。
dns.resolveCname(hostname, callback) 和 dns.resolve() 类似, 仅能进行别名记录查询 (CNAME记录)。addresses 是对 hostname 可用的别名记录数组 (比如,, [‘bar.example.com’])。
dns.reverse(ip, callback) 反向解析 IP 地址,指向该 IP 地址的域名数组。
dns.getServers() 返回一个用于当前解析的 IP 地址数组的字符串。
dns.setServers(servers) 指定一组 IP 地址作为解析服务器。

rrtypes

以下列出了 dns.resolve() 方法中有效的 rrtypes值:

  • A,IPV4 地址, 默认
  • AAAA, IPV6 地址
  • MX, 邮件交换记录
  • TXT, text 记录
  • SRV, SRV 记录
  • PTR, 用来反向 IP 查找
  • NS, 域名服务器记录
  • CNAME, 别名记录
  • SOA, 授权记录的初始值

错误码

DNS 查询返回的错误码:

  • dns.NODATA: 无数据响应。
  • dns.FORMERR: 查询格式错误。
  • dns.SERVFAIL: 常规失败。
  • dns.NOTFOUND: 没有找到域名。
  • dns.NOTIMP: 未实现请求的操作。
  • dns.REFUSED: 拒绝查询。
  • dns.BADQUERY: 查询格式错误。
  • dns.BADNAME: 域名格式错误。
  • dns.BADFAMILY: 地址协议不支持。
  • dns.BADRESP: 回复格式错误。
  • dns.CONNREFUSED: 无法连接到 DNS 服务器。
  • dns.TIMEOUT: 连接 DNS 服务器超时。
  • dns.EOF: 文件末端。
  • dns.FILE: 读文件错误。
  • dns.NOMEM: 内存溢出。
  • dns.DESTRUCTION: 通道被摧毁。
  • dns.BADSTR: 字符串格式错误。
  • dns.BADFLAGS: 非法标识符。
  • dns.NONAME: 所给主机不是数字。
  • dns.BADHINTS: 非法HINTS标识符。
  • dns.NOTINITIALIZED: c/c-ares 库未初始化。
  • dns.LOADIPHLPAPI: 加载 iphlpapi.dll 出错。
  • dns.ADDRGETNETWORKPARAMS: 无法找到 GetNetworkParams 函数。
  • dns.CANCELLED: 取消 DNS 查询。

示例

main.js

var dns = require("dns");
dns.lookup("echarts.apache.org", function onLookup(err, address, family) {
  console.log("ip 地址:", address);
  dns.reverse(address, function (err, hostnames) {
    if (err) {
      console.log(err.stack);
    }
    console.log("反向解析 " + address + ": " + JSON.stringify(hostnames));
  });
});
//终端执行 node main.js
//输出
// ip 地址: 151.101.2.132
// Error: getHostByAddr ENOTFOUND 151.101.2.132
//     at QueryReqWrap.onresolve [as oncomplete] (node:internal/dns/callback_resolver:47:19)
// 反向解析 151.101.2.132: undefined

Net 模块

Node.js Net 模块提供了一些用于底层的网络通信的小工具,包含了创建服务器/客户端的方法

使用方式

var net = require("net")

方法概览

方法 描述
net.createServer([options][, connectionListener]) 创建一个 TCP 服务器。 connectionListener 自动给 connection 事件创建监听器
net.connect(options[, connectionListener]) 返回一个新的 net.Socket,并连接到指定的地址和端口。当 socket 建立的时候,将会触发 connect 事件。
net.createConnection(options[, connectionListener]) 创建端口为 port 和主机为host的 TCP 连接。host 默认为 localhost
net.connect(port[, host][, connectListener]) 创建端口为 port 和主机为 host的 TCP 连接 。host 默认为 localhost。connectListener 作为监听器添加到 connect 事件。返回 net.Socket
net.createConnection(port[, host][, connectListener]) 创建端口为 port 和主机为 host的 TCP 连接 。host 默认为 localhost。connectListener 作为监听器添加到 connect 事件。返回 net.Socket
net.connect(path[, connectListener]) 创建连接到 path 的 unix socket 。connectListener 作为监听器添加到 connect 事件上。返回 net.Socket
net.createConnection(path[, connectListener]) 创建连接到 path 的 unix socket 。connectListener 作为监听器添加到 connect 事件。返回 net.Socket
net.isIP(input) 检测input是否为 IP 地址.IPV4 返回 4,IPV6 返回 6,其他情况返回 0
net.isIPv4(input) 如果input地址为 IPV4,返回 true,否则false
net.isIPv6(input) 如果input地址为 IPV6,返回 true,否则false

net.Server

net.Server通常用于创建一个 TCP 或本地服务器:

方法

方法 描述
server.listen(port[, host][, backlog][, callback]) 监听端口 port 和 主机 host ac连接。 默认 host 接受任何 IPv4 地址(INADDR_ANY)的直接连接。端口 port 为 0 时,则会随机分配端口
server.listen(path[, callback]) 通过指定 path 的连接,启动一个本地 socket 服务器
server.listen(handle[, callback]) 通过指定句柄连接
server.listen(options[, callback]) options 的属性:端口 port, 主机 host, 和 backlog, 以及可选参数 callback 函数, 例如server.listen(port, [host], [backlog], [callback])。参数 path 可以指定 UNIX socket
server.close([callback]) 服务器停止接收新的连接,保持现有连接。异步函数,当所有连接结束的时候服务器会关闭,并会触发 close 事件
server.address() 操作系统返回绑定的地址,协议族名和服务器端口
server.unref() 如果这是事件系统中唯一一个活动的服务器,调用 unref 将允许程序退出。
server.ref() 与 unref 相反,如果这是唯一的服务器,在之前被 unref 了的服务器上调用 ref 将不会让程序退出(默认行为)。如果服务器已经被 ref,再次调用 ref 不会产生影响。
server.getConnections(callback) 异步获取服务器当前活跃连接的数量。当 socket 发送给子进程后才有效;回调函数有 2 个参数 err 和 count。

事件

事件 描述
listening 当服务器调用 server.listen 绑定后会触发
connection 当新连接创建后会被触发。socket 是 net.Socket实例
close 服务器关闭时会触发。注意,如果存在连接,这个事件不会被触发直到所有的连接关闭
error 发生错误时触发。close 事件将被下列事件直接调用

net.Socket

net.Socket 对象是 TCP 或 UNIX Socket 的抽象。net.Socket 实例实现了一个双工流接口。可以在用户创建客户端(使用 connect())时使用, 或者由 Node 创建它们,并通过 connection 服务器事件传递给用户

net.Socket 事件

事件 描述
lookup 在解析域名后,但在连接前,触发该事件。对 UNIX sokcet 不适用
connect 成功建立 socket 连接时触发
data 当接收到数据时触发
end 当 socket 另一端发送 FIN 包时,触发
timeout 当 socket 空闲超时时触发,仅表明 socket 已经空闲。用户必须手动关闭连接
drain 当写缓存为空得时候触发。可用来控制上传
error 错误发生时触发
close 当 socket 完全关闭时触发。参数 had_error 是布尔值,它表示是否因为传输错误导致 socket 关闭

属性

net.Socket 提供了很多有用的属性,便于控制 socket 交互:

属性 描述
socket.bufferSize 该属性显示了要写入缓冲区的字节数
socket.remoteAddress 远程的 IP 地址字符串,例如:74.125.127.100/2001:4860:a005::68。
socket.remoteFamily 远程IP协议族字符串,比如 IPv4/IPv6
socket.remotePort 远程端口,数字表示,例如:80/21
socket.localAddress 网络连接绑定的本地接口 远程客户端正在连接的本地 IP 地址,字符串表示。例如,如果你在监听0.0.0.0而客户端连接在192.168.1.1,这个值就会是192.168.1.1
socket.localPort 本地端口地址,数字表示。例如:80/21
socket.bytesRead 接收到得字节数
socket.bytesWritten 发送的字节数

方法

属性 描述
new net.Socket([options]) 构造一个新的 socket 对象
socket.connect(port[, host][, connectListener]) 指定端口 port 和 主机 host,创建 socket 连接 。host 默认为 localhost。通常情况不需要使用 net.createConnection 打开 socket。只有实现了自己的 socket 时才会用到
socket.connect(path[, connectListener]) 打开指定路径的 unix socket。通常情况不需要使用 net.createConnection 打开 socket。只有实现了自己的 socket 时才会用到
socket.setEncoding([encoding]) 设置编码
socket.write(data[, encoding][, callback]) 在 socket 上发送数据。第二个参数指定了字符串的编码,默认是 UTF8 编码。
socket.end([data][, encoding]) 半关闭 socket。例如,它发送一个 FIN 包。可能服务器仍在发送数据。
socket.destroy() 确保没有 I/O 活动在这个套接字上。只有在错误发生情况下才需要。(处理错误等等)。
socket.pause() 暂停读取数据。就是说,不会再触发 data 事件。对于控制上传非常有用。
socket.resume() 调用 pause() 后想恢复读取数据。
socket.setTimeout(timeout[, callback]) socket 闲置时间超过 timeout 毫秒后 ,将 socket 设置为超时。
socket.setNoDelay([noDelay]) 禁用纳格(Nagle)算法。默认情况下 TCP 连接使用纳格算法,在发送前他们会缓冲数据。将 noDelay 设置为 true 将会在调用 socket.write() 时立即发送数据。noDelay 默认值为 true
socket.setKeepAlive([enable][, initialDelay]) 禁用/启用长连接功能,并在发送第一个在闲置 socket 上的长连接 probe 之前,可选地设定初始延时。默认为 false。 设定 initialDelay (毫秒),来设定收到的最后一个数据包和第一个长连接probe之间的延时。将 initialDelay 设为0,将会保留默认(或者之前)的值。默认值为0
socket.address() 操作系统返回绑定的地址,协议族名和服务器端口。返回的对象有 3 个属性,比如{ port: 12346, family: IPv4, address: 127.0.0.1 }
socket.unref() 如果这是事件系统中唯一一个活动的服务器,调用 unref 将允许程序退出。如果服务器已被 unref,则再次调用 unref 并不会产生影响
socket.ref() 与 unref 相反,如果这是唯一的服务器,在之前被 unref 了的服务器上调用 ref 将不会让程序退出(默认行为)。如果服务器已经被 ref,则再次调用 ref 并不会产生影响

示例

server.js 文件:

var net = require("net");
var server = net.createServer(function (connection) {
  console.log("client connected");
  connection.on("end", function () {
    console.log("客户端关闭连接");
  });
  connection.write("Hello World!\r\n");
  connection.pipe(connection);
});
server.listen(8080, function () {
  console.log("server is listening");
});
//终端执行 node server.js
//输出
// server is listening

client.js 文件:

var net = require("net");
var client = net.connect({ port: 8080 }, function () {
  console.log("连接到服务器!");
});
client.on("data", function (data) {
  console.log(data.toString());
  client.end();
});
client.on("end", function () {
  console.log("断开与服务器的连接");
});
//终端执行 node main.js
//输出
// 连接到服务器!
// Hello World!
// 断开与服务器的连接

os

提供基本的系统操作函数,主要是用于处理与操作系统相关的功能模块

使用方式

var os = require("os")

方法概览

方法 描述
os.tmpdir() 返回操作系统的默认临时文件夹
os.endianness() 返回 CPU 的字节序,可能返回 “BE” 或 “LE”。
os.hostname() 返回操作系统的主机名
os.type() 返回操作系统名
os.platform() 返回编译时的操作系统名
os.arch() 返回操作系统 CPU 架构,可能返回 “x64”、“arm” 和 “ia32”
os.release() 返回操作系统的发行版本
os.uptime() 返回操作系统运行的时间,以秒为单位
os.loadavg() 返回一个包含 1、5、15 分钟平均负载的数组。
os.totalmem() 返回系统内存总量,单位为字节
os.freemem() 返回操作系统空闲内存量,单位是字节
os.cpus() 返回一个对象数组,包含所安装的每个 CPU/内核的信息:型号、速度(单位 MHz)、时间(一个包含 user、nice、sys、idle 和 irq 所使用 CPU/内核毫秒数的对象)
os.networkInterfaces() 获得网络接口列表

os的属性:

  • os.EOL:定义了操作系统的行尾符的常量。

示例

main.js 文件:

var os = require("os");
console.log("endianness : " + os.endianness()); // CPU 的字节序
console.log("type : " + os.type()); // 操作系统名
console.log("platform : " + os.platform()); // 操作系统名
console.log("Total memory : " + os.totalmem() + " bytes."); // 系统内存总量
console.log("Free memory : " + os.freemem() + " bytes."); // 操作系统空闲内存量
//终端执行 node main.js
//输出
// endianness : LE
// type : Windows_NT
// platform : win32
// Total memory : 17015451648 bytes.
// Free memory : 5720956928 bytes.

util

是Node.js的核心模块,提供了一些常用函数的合集,弥补javascript功能过于精简的问题

使用方式

const util = require('util');

常用方法

util.callbackify

util.callbackify(original) 将 async 异步函数(或者返回值为 Promise 的函数)转换成遵循异常优先回调风格的函数.例如将 (err, value) => … 回调作为最后一个参数。 在回调中,err为拒绝(Promise reject)的原因(若Promise resolve,则err为 null),value则是解决的值。

const util = require('util');

async function fn() {
  return 'hello world';
}
const callbackFunction = util.callbackify(fn);

callbackFunction((err, ret) => {
  if (err) throw err;
  console.log(ret);
});
//输出
//hello world

回调函数是异步执行的,并且有异常堆栈错误追踪。 如果回调函数抛出一个异常,进程会触发一个 ‘uncaughtException’ 异常,如果没有被捕获,进程将会退出。

null 在回调函数中作为一个参数有其特殊的意义,如果回调函数的首个参数为 Promise 拒绝的原因且带有返回值,且值可以转换成布尔值 false,这个值会被封装在 Error 对象里,可以通过属性 reason 获取。

function fn() {
  return Promise.reject(null);
}
const callbackFunction = util.callbackify(fn);
callbackFunction((err, ret) => {
  //Promise 被以 `null` reject时,被包装为Error并且原始值存储在 `reason` 中
  err && err.hasOwnProperty('reason') && err.reason === null;  // true
});

original 为 async 异步函数,该函数返回传统回调函数。

util.inherits

util.inherits(constructor, superConstructor) 是一个实现对象间原型继承的函数。已经废弃。
JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同。JavaScript 没有提供对象继承的语言级别特性,而是通过原型复制来实现的。所以constructor继承superConstructor的原型

var util = require('util'); 
function Base() { 
    this.name = 'base'; 
    this.base = 1991; 
    this.sayHello = function() { 
      console.log('Hello ' + this.name); 
    }; 
} 
Base.prototype.showName = function() { 
    console.log(this.name);
}; 
function Sub() { 
    this.name = 'sub'; 
} 
util.inherits(Sub, Base); 
var objBase = new Base(); 
objBase.showName(); //base
objBase.sayHello(); //Hello base
console.log(objBase); //Base { name: 'base', base: 1991, sayHello: [Function (anonymous)] }
var objSub = new Sub(); 
objSub.showName(); //sub
//objSub.sayHello(); 
console.log(objSub); //Sub { name: 'sub' }

定义的基础对象 Base 和一个继承 Base 的 Sub,Base 有三个在构造函数内定义的属性和一个原型中定义的函数,通过util.inherits 实现继承。运行结果请查看上述注释

注意:Sub 仅仅继承了 Base 在原型中定义的函数,而Base构造函数内部创造的属性和函数都没有被 Sub 继承。

所以如果去掉 objSub.sayHello(); 这行的注释就会报错:TypeError: objSub.sayHello is not a function

在原型中定义的属性不会被 console.log 作为对象的属性输出

因为当前继承方式已废弃,现有继承方法:

class Base {
  name = "base";
  base = 1991;
  sayHello = function () {
    console.log("Hello " + this.name);
  };
}
Base.prototype.showName = function () {
  console.log(this.name);
};
class Sub extends Base {
  name = "sub";
}
var objBase = new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub = new Sub();
objSub.showName();
objSub.sayHello();
console.log(objSub);
//输出:
// base
// Hello base
// Base { name: 'base', base: 1991, sayHello: [Function: sayHello] }
// sub
// Hello sub
// Sub { name: 'sub', base: 1991, sayHello: [Function: sayHello] }

extends 方式,不论是原型还是构造函数中的属性与方法均继承

util.inspect

util.inspect(object,[showHidden],[depth],[colors]) 是一个将任意对象转换 为字符串的方法,通常用于调试和错误输出。

  • object,必填参数,即要转换的对象
  • showHidden ,可选参数,值为 true,将会输出更多隐藏信息。
  • depth,可选参数,表示最大递归的层数,默认值为2.如果对象很复杂,可以指定depth 以控制输出信息的层数。如果depth指定为 null 表示将无限递归层数完整遍历对象。
  • colors,可选参数,如果 colors 为 true,输出格式将会以 ANSI 颜色编码,通常用于在终端显示更漂亮的效果。

特别要指出的是,util.inspect 并不会简单地直接把对象转换为字符串,即使该对象定义了 toString 方法也不会调用。

var util = require('util'); 
function Person() { 
    this.name = 'byvoid'; 
    this.toString = function() { 
    return this.name; 
    }; 
} 
var obj = new Person(); 
console.log(util.inspect(obj)); 
console.log(util.inspect(obj, true)); 
//输出
// Person { name: 'byvoid', toString: [Function (anonymous)] }
// Person {
//   name: 'byvoid',
//   toString:  [Function (anonymous)] {
//     [length]: 0,
//     [name]: '',
//     [arguments]: null,
//     [caller]: null,
//     [prototype]: { [constructor]: [Circular *1] }
//   }
// }

util.isArray

util.isArray(object),如果给定的参数 “object” 是一个数组返回 true,否则返回 false

var util = require('util');
util.isArray([])// true
util.isArray(new Array)// true
util.isArray({})// false

util.isRegExp

util.isRegExp(object),如果参数 “object” 是一个正则表达式返回true,否则返回false。

var util = require('util');
util.isRegExp(/some regexp/)// true
util.isRegExp(new RegExp('another regexp'))// true
util.isRegExp({}) // false

util.isDate

util.isDate(object),如果参数 “object” 是一个日期,返回true,否则返回false。

var util = require('util');
util.isDate(new Date())  // true
util.isDate(Date())  // false (without 'new' returns a String)
util.isDate({})  // false

如何调试

node --inspect-brk xxx.js
chrome 浏览器输入网址:
chrome://inspect
检查当前被调试的程序

   <script type="text/javascript">
      function loadScript() {
        console.log("current loadScript is");
        let script = document.createElement("script");
        script.type = "text/javascript";
        script.src = "<%= BASE_URL %>env.js";
        script.async=false;
       document.head.appendChild(script);
      }
      console.log("current BASE_URL is"+"<%= BASE_URL %>");
      // if("<%= BASE_URL %>"!==""){

      // }
      window.function(){
        loadScript();
      }
   </script>

你可能感兴趣的:(前端,node.js)