[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.<anonymous> (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: <ref *1> [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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/267872.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一篇文章拿捏继承多态练习题

继承多态习题 选择题解释 简答题 选择题 下面哪种面向对象的方法可以让你变得富有( ) A: 继承 B: 封装 C: 多态 D: 抽象 ( )是面向对象程序设计语言中的一种机制。这种机制实现了方法的定义与具体的对象无关&#xff0c; 而对方法的调用则可以关联于具体的对象。 A: 继承 B: 模…

Linux系统编程(六):进程(下)

参考引用 UNIX 环境高级编程 (第3版)嵌入式Linux C应用编程-正点原子 1. 进程与程序 1.1 main() 函数由谁调用&#xff1f; C 语言程序总是从 main 函数开始执行int main(void) int main(int argc, char *argv[]) // 如果需要向应用程序传参&#xff0c;则选择该种写法操作系…

TikTok真题第3天 | 856.括号的分数、2115. 从给定原材料中找到所有可以做出的菜、394.字符串解码

856.括号的分数 题目链接&#xff1a;856.score-of-parentheses 解法&#xff1a; leetcode官方的题解基本是每个字都认得&#xff0c;连起来就看不懂。 使用栈来解决&#xff0c;后进先出&#xff0c;后面加入的左括号&#xff0c;先弹出和右括号去匹配。定义一个记录分数…

部署LNMP动态网站

部署LNMP动态网站 安装LNMP平台相关软件1. 安装软件包2. 启动服务&#xff08;nginx、mariadb、php-fpm&#xff09;3. 修改Nginx配置文件&#xff0c;实现动静分离4. 配置数据库 上线wordpress代码 &#xff08;测试搭建的LNMP环境是否可以使用&#xff09;1. 上线php动态网站…

什么等等? I/O Wait ≠ I/O 瓶颈?

本文地址&#xff1a;什么等等&#xff1f; I/O Wait ≠ I/O 瓶颈&#xff1f; | 深入浅出 eBPF 1. I/O Wait 定义2. 测试验证3. 进一步明确磁盘吞吐和读写频繁进程4. 内核 CPU 统计实现分析5. 总结参考资料 1. I/O Wait 定义 I/O Wait 是针对单个 CPU 的性能指标&#xff0…

Bresenham 算法

1965 年&#xff0c;Bresenham 为数字绘图仪开发了一种绘制直线的算法&#xff0c;该算法同样使用于光栅扫描显示器&#xff0c;被称为 Bresenham 算法。 原理 算法的目标是选择表示直线的最佳光栅位置。Bresenhan 算法在主位移方向上每次递增一个单位。另一个方向的增量为 0…

【java爬虫】基于springboot+jdbcTemplate+sqlite+OkHttp获取个股的详细数据

注&#xff1a;本文所用技术栈为&#xff1a;springbootjdbcTemplatesqliteOkHttp 前面的文章我们获取过沪深300指数的成分股所属行业以及权重数据&#xff0c;本文我们来获取个股的详细数据。 我们的数据源是某狐财经&#xff0c;接口的详细信息在下面的文章中&#xff0c;本…

抖店对接厂家时,厂家不愿提供ERP打单如何解决?相关解答如下

我是王路飞。 现在的抖店已经不能拍单了&#xff0c;只能让厂家使用抖音电子面单发货。 关于这件事&#xff0c;我之前也说过&#xff0c;无货源商家太聪明了&#xff0c;所以平台一定会解决拍单问题的&#xff0c;无非是个时间问题罢了。 而且我认为这对我们商家来说也是个…

关于巴西网络犯罪分子使用LOLBaS和CMD脚本窃取银行账户的动态情报

一、基本内容 最近&#xff0c;一名未知身份的网络犯罪威胁行为者以使用西班牙语和葡萄牙语的用户为目标&#xff0c;破坏墨西哥、秘鲁和葡萄牙等地的网上银行账户。该攻击链主要利用社会工程学技术&#xff0c;利用葡萄牙和西班牙用户的电子邮件&#xff0c;发送带有欺骗性的…

如何使用固定二级子域名公网访问多个本地Windows Web网站

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…

图像识别SLIC、Haralick texture features(自备)

SLIC 简单线性迭代聚类(SLIC ),它采用k-means聚类方法来有效地生成超像素。 SLIC超像素分割详解&#xff08;一&#xff09;&#xff08;二&#xff09;&#xff08;三&#xff09;_超像素分割 样本-CSDN博客 超像素分割 & SLIC算法 & 使用示例_slic分割算法matlab-C…

快速剪辑视频软件,视频图像翻转软件

在这个信息爆炸的时代&#xff0c;视频已经成为了人们获取信息、娱乐、学习的主要方式之一。一个好的视频&#xff0c;不仅可以吸引观众的眼球&#xff0c;更可以传达出深层次的意义。那该什么快速的编辑视频&#xff0c;有没有好用的工具推荐呢&#xff1f;今天小编就给大家介…

MySQL数据库——约束

1. 约束 1.1. 概述 概述 约束是MySQL中用于限制表中数据规则的术语。这些规则可以确保数据类型、长度、精度等符合要求&#xff0c;并保持数据的正确性、有效性和完整性。约束可以应用于表中的字段&#xff0c;并帮助保护数据库中的数据免受无效或错误数据的干扰。 分类 约束…

行为型模式

目录 行为型模式1 模板方法模式1.1 概述1.2 结构1.3 案例实现1.3 优缺点1.4 适用场景1.5 JDK源码解析 2 策略模式2.1 概述2.2 结构2.3 案例实现2.4 优缺点2.5 使用场景2.6 JDK源码解析 3 命令模式3.1 概述3.2 结构3.3 案例实现3.4 优缺点3.5 使用场景3.6 JDK源码解析 4 责任链模…

多线程的基本使用与多线程中条件变量的使用——消费者生产者问题实例

多线程的基本使用与多线程中条件变量的使用——消费者生产者问题实例 本文主要涉及多线程的使用方法&#xff0c;通过两个实例来对多线程的使用进行理解&#xff0c; 案例包括&#xff1a; 1.一个线程负责计数&#xff0c;另一个线程负责打印计数值 2.消费者生产者问题 文章目录…

Git常用命令及解释说明

目录 前言1 git config2 git init3 git status4 git add5 git commit6 git reflog7 git log8 git reset结语 前言 Git是一种分布式版本控制系统&#xff0c;广泛用于协作开发和管理项目代码。了解并熟练使用Git的常用命令对于有效地管理项目版本和历史记录至关重要。下面是一些…

[THUPC 2024 初赛] 二进制 (树状数组单点删除+单点查询)(双堆模拟set)

题解 题目本身不难想 首先注意到所有查询的序列长度都是小于logn级别的 我们可以枚举序列长度len&#xff0c;然后用类似滑动窗口的方法&#xff0c;一次性预处理出每种字串的所有出现位置&#xff0c;也就是开N个set去维护所有的位置。预处理会进行O(logn)轮&#xff0c;每…

基于谷歌模型gemini-pro 的开发的QT 对话项目

支持的功能&#xff0c;新建对话框&#xff0c;目前发现相关梯子不支持访问谷歌的api 的可能代理设置的不对&#xff0c; QNetworkAccessManager manager;// Set up your requestQNetworkRequest request;request.setUrl(QUrl("https://generativelanguage.googleapis.com…

这一平台只要把握住风口期,自己就能当老板!

我是电商珠珠 短视频渐渐走进大家的视野&#xff0c;改变了大家的日常娱乐方式。从19年开始&#xff0c;抖音开始发展电商平台-抖音小店。 在改变大家娱乐方式的同时&#xff0c;还将直播电商的热度掀了起来&#xff0c;由此改变了大家的购物方式&#xff0c;给大家带来了方便…

ansible-playbook实操之一键搭建lnmp+wordpress

目录 1、架构和准备&#xff1a; 2、配置nginx角色&#xff1a; 3、配置mariadb角色&#xff1a; 4、配置php角色&#xff1a; 5、配置完之后&#xff0c;写脚本调用roles 6、配置完之后浏览器搭建wordpress&#xff1a; 1、架构和准备&#xff1a; 操控节点&#xff1a;…