技术标签: node.js
Node.js是一个基于Chrome V8引擎的JavaScript运行时环境,用于构建高性能、可扩展的网络应用程序。它允许使用JavaScript进行服务器端编程,使开发者能够在前后端都使用同一种编程语言。Node.js采用了事件驱动、非阻塞I/O模型,可以处理大量并发连接,适合构建实时应用和高吞吐量的网络服务。
Node.js最初由Ryan Dahl于2009年创建,并在短时间内获得了广泛的关注和采用。最初的目标是解决传统的Web服务器模型中I/O阻塞的问题,通过引入非阻塞I/O和事件驱动的方式提高了服务器的性能和并发能力。自发布以来,Node.js社区不断壮大,出现了许多优秀的第三方库和框架,使得Node.js成为全球范围内广泛采用的技术之一。
JavaScript是一种广泛使用的脚本语言,最初设计用于在网页上添加交互和动态效果。Node.js使用JavaScript作为服务器端编程语言,因此对JavaScript的理解至关重要。JavaScript是一种解释型、高级的、动态类型的语言,具有面向对象和函数式编程的特性。熟悉JavaScript的语法、数据类型、函数和作用域等概念对于理解Node.js的工作原理至关重要。
Node.js采用了事件驱动和非阻塞I/O模型,这是其实现高性能和高并发的关键。事件驱动指的是Node.js通过触发和处理各种事件来进行异步操作。在Node.js中,某个操作完成后会触发一个事件,然后相应的回调函数被执行。非阻塞I/O表示在进行I/O操作时,Node.js不会停止其他任务的执行,而是继续执行下一个任务,当I/O操作完成时再执行回调函数。这种模型使得Node.js能够在单个线程上处理大量并发请求,提高了系统的响应能力。
V8引擎是Node.js的核心之一,它是由Google开发的高性能JavaScript引擎。V8引擎将JavaScript代码转换为机器码,使得JavaScript代码能够在计算机上快速执行。它采用了即时编译(JIT)技术和垃圾回收机制,优化了JavaScript的执行效率和内存管理。
Node.js运行时是单线程的,这意味着它在同一时间只能处理一个请求。但是,Node.js通过事件循环机制实现了并发处理。事件循环是一个不断运行的循环,负责监听和分发事件,执行相应的回调函数。当有异步操作完成时,会将对应的回调函数放入事件队列中,等待事件循环来处理。这种单线程的事件循环机制使得Node.js可以高效地处理并发请求,避免了线程切换的开销和同步编程带来的复杂性。
在Node.js中,模块化是一种重要的编程概念。它允许我们将代码拆分成可复用的模块,每个模块都有自己的作用域和功能。通过使用require
方法,我们可以在一个模块中引入其他模块,并使用其提供的功能。require
方法是Node.js中的内置函数,用于加载和引入模块。
fs
模块是Node.js的核心模块之一,用于对文件进行读取、写入、修改等操作。例如,我们可以使用fs.readFile
方法读取文件内容,使用fs.writeFile
方法写入文件内容,以及使用fs.readdir
方法读取目录内容等。const fs = require('fs');
// 读取文件内容
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// 写入文件内容
fs.writeFile('file.txt', 'Hello, Node.js!', (err) => {
if (err) throw err;
console.log('File written successfully!');
});
http
模块是Node.js用于创建Web服务器的核心模块。通过使用http.createServer
方法,我们可以创建一个HTTP服务器,并监听指定的端口。以下是一个简单的示例:const http = require('http');
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, World!');
});
server.listen(3000, 'localhost', () => {
console.log('Server running at http://localhost:3000/');
});
path
模块是Node.js用于处理文件路径的核心模块。它提供了一些有用的方法,用于获取、解析和拼接文件路径。例如,我们可以使用path.join
方法拼接路径,使用path.resolve
方法解析路径,以及使用path.basename
方法获取文件名等。const path = require('path');
const fullPath = path.join('folder', 'file.txt');
console.log(fullPath); // 输出: folder/file.txt
const resolvedPath = path.resolve('folder', 'file.txt');
console.log(resolvedPath); // 输出: /home/user/folder/file.txt
const basename = path.basename('/home/user/folder/file.txt');
console.log(basename); // 输出: file.txt
events
模块是Node.js引入的事件驱动模块。它提供了构建和处理事件的基本机制。我们可以通过继承events.EventEmitter
类创建自定义的事件并监听它们。以下是一个简单的示例:const EventEmitter = require('events');
class MyEmitter extends EventEmitter {
}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('Event emitted');
});
myEmitter.emit('event'); // 输出: Event emitted
util
模块用于实用工具方法,crypto
模块用于加密和解密,stream
模块用于处理流数据等。根据具体需求,我们可以引入并使用这些模块来扩展Node.js的功能。NPM(Node Package Manager)是 Node.js 的官方包管理工具,可以帮助我们方便地安装、管理和分享 JavaScript 包。它是基于命令行操作的工具,在安装 Node.js 时会一同安装。以下是在不同操作系统上安装 NPM 的方法:
npm --version
如果显示了 NPM 的版本号,则表示已成功安装。
npm --version
如果显示了 NPM 的版本号,则表示已成功安装。
package.json 是一个描述项目信息和依赖关系的 JSON 文件,用于管理项目的配置和依赖项。我们可以使用以下命令来初始化一个新的 package.json 文件:
npm init
在初始化过程中,NPM 会向我们提供一些问题,例如项目名称、版本号、描述等。我们可以根据需求回答这些问题,最后生成一个 package.json 文件。
npm install
命令,后跟要安装的包名。例如,要安装 lodash 包,可以运行以下命令:npm install lodash
这将在当前项目的 node_modules 目录中下载并安装 lodash 包。
npm update
命令,后跟要更新的包名。例如,要更新 lodash 包,可以运行以下命令:npm update lodash
这将检查是否有可用的更新,并更新 lodash 包。
npm uninstall
命令,后跟要删除的包名。例如,要删除 lodash 包,可以运行以下命令:npm uninstall lodash
这将从当前项目的 node_modules 目录中删除 lodash 包。
在使用第三方包和管理依赖时,我们应该遵循以下最佳实践:
确定所需功能:在选择和使用第三方包之前,先确定项目所需的功能,并选择最适合的包。
了解包的质量和维护情况:查看包的文档、社区活跃度和更新频率,确保选择的包是高质量且得到良好维护的。
版本控制:在 package.json 文件中精确指定所使用的包的版本号,以确保在不同环境中的一致性。
使用语义化版本控制:在指定包的版本号时,使用语义化版本规范(Semantic Versioning),例如 MAJOR.MINOR.PATCH。
更新依赖:定期检查项目的依赖项,并更新到最新版本,以获取新功能、修复 bug 和安全漏洞等。
使用锁文件:在项目中使用锁文件(例如 package-lock.json 或 yarn.lock)来确保在不同环境中安装一致的依赖版本。
文档和示例:阅读并理解依赖包的文档和示例,以更好地使用和集成它们。
通过遵循这些最佳实践,我们可以更好地管理和使用第三方包,并确保项目的稳定性和安全性。
Express是一个快速、灵活且具有简洁API的Node.js Web应用程序框架。它使用了极简主义的设计理念,使得构建Web应用变得非常简单和高效。以下是使用Express框架的概述和安装步骤:
概述:Express提供了一组方法和工具,用于处理HTTP请求、路由URL、渲染视图、处理中间件等常见的Web应用程序任务。它还支持在应用程序中使用模板引擎、处理表单数据、处理文件上传等功能。
安装:要安装Express框架,可以在项目的根目录下使用NPM进行安装。运行以下命令:
npm install express
这将在项目的node_modules
目录中安装Express框架。
在Express中,创建一个简单的Web服务器非常容易。以下是一个基本的示例:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
上述代码创建了一个Express应用程序,并在根路径上定义了一个GET路由。当访问根路径时,服务器会向客户端发送"Hello, world!"。
Express提供了灵活且易于使用的路由和中间件功能。路由用于定义不同路径和HTTP方法的处理程序,而中间件用于在请求和响应之间执行额外的逻辑。以下是一些示例:
// 路由示例
app.get('/', (req, res) => {
// 处理根路径的GET请求
});
app.post('/users', (req, res) => {
// 处理/users路径的POST请求
});
// 中间件示例
app.use(express.json()); // 解析JSON格式的请求体
app.use(express.static('public')); // 提供静态文件服务
在Express中,处理表单数据和文件上传非常简单。可以使用body-parser
中间件来解析表单数据,并使用multer
中间件来处理文件上传。以下是一个示例:
const bodyParser = require('body-parser');
const multer = require('multer');
app.use(bodyParser.urlencoded({
extended: false }));
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/'); // 上传的文件保存在uploads/目录下
},
filename: (req, file, cb) => {
cb(null, Date.now() + '-' + file.originalname); // 为上传的文件生成唯一的文件名
}
});
const upload = multer({
storage });
app.post('/upload', upload.single('file'), (req, res) => {
// 处理文件上传请求
});
上述代码使用body-parser
中间件来解析表单数据,并使用multer
中间件设置文件上传的配置。在路由处理程序中,我们使用upload.single('file')
来处理单个文件上传,并将上传的文件保存在uploads/
目录下。
在Express中处理错误和记录日志是非常重要的,可以使用中间件来实现这些功能。以下是一个简单的示例:
app.use((err, req, res, next) => {
console.error(err);
res.status(500).send('Internal Server Error');
});
app.use((req, res, next) => {
console.log(`${
req.method} ${
req.url}`);
next();
});
上述代码定义了两个中间件函数,一个用于处理错误,另一个用于记录请求的方法和路径。第一个中间件函数在发生错误时打印错误信息,并向客户端发送500状态码。第二个中间件函数在每个请求之前记录请求的方法和路径。
在选择数据库时,需要考虑项目的需求、数据模型和性能要求。下面是一些常见的数据库选择:
关系型数据库(如MySQL、PostgreSQL):适用于需要保持结构化数据完整性和复杂查询的场景。
非关系型数据库(如MongoDB、Redis):适用于需要灵活的数据模型和高扩展性的场景。
内存数据库(如Memcached、Redis):适用于对读写速度有很高要求的场景。
对于数据库的安装,可以按照官方文档提供的步骤进行安装。
要连接数据库,可以使用相应数据库的官方客户端或第三方库。以下是使用Node.js连接MySQL和MongoDB的示例:
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydatabase'
});
connection.connect((err) => {
if (err) throw err;
console.log('Connected to MySQL database');
});
上述代码创建了一个MySQL连接,并指定了主机、用户名、密码和数据库名称。连接成功后,会输出"Connected to MySQL database"。
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mydatabase', {
useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log('Connected to MongoDB database');
})
.catch((err) => {
console.error(err);
});
上述代码使用Mongoose库连接到MongoDB数据库。连接字符串指定了主机和数据库名称,连接成功后会输出"Connected to MongoDB database"。
ORM(对象关系映射)库可以简化对数据库的操作,使开发人员可以使用面向对象的方式来处理数据。以下是使用Sequelize进行数据操作的示例:
npm install sequelize
const {
Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('mydatabase', 'username', 'password', {
host: 'localhost',
dialect: 'mysql'
});
const User = sequelize.define('User', {
username: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false
}
});
(async () => {
await sequelize.sync(); // 同步数据库模型
// 在此进行数据操作
})();
上述代码使用Sequelize连接到MySQL数据库,并定义了一个名为User的模型,它有两个属性:username和email。
// 创建用户
await User.create({
username: 'John', email: '[email protected]' });
// 查询用户
const users = await User.findAll();
// 更新用户
await User.update({
username: 'Jane' }, {
where: {
id: 1 } });
// 删除用户
await User.destroy({
where: {
id: 1 } });
上述代码示例了创建、查询、更新和删除用户的操作。
在JavaScript中,回调函数是一种常见的处理异步操作的方式。通过将函数作为参数传递给其他函数,在异步操作完成后执行回调函数来处理结果。
示例使用回调函数处理异步操作的代码:
function fetchData(callback) {
// 模拟异步操作
setTimeout(() => {
const data = 'Hello, World!';
callback(data);
}, 1000);
}
function processData(data) {
console.log(data);
}
fetchData(processData); // 输出:Hello, World!
然而,使用回调函数存在一些问题,例如嵌套过多的回调函数导致代码难以理解(即回调地狱),以及难以处理多个异步操作的并发等。
为了解决回调函数带来的问题,ES6引入了Promise对象。它是一种代表异步操作最终完成或失败的对象。
示例使用Promise处理异步操作的代码:
function fetchData() {
return new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
const data = 'Hello, World!';
resolve(data);
// 或者 reject(new Error('操作失败'));
}, 1000);
});
}
fetchData()
.then(data => {
console.log(data); // 输出:Hello, World!
})
.catch(error => {
console.error(error);
});
通过Promise,我们可以将异步操作封装为一个Promise对象,并使用.then()
和.catch()
方法处理操作成功和失败的情况。
Promise还支持链式调用,使多个异步操作按顺序执行。
示例使用Promise链式调用的代码:
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = 'Hello, World!';
resolve(data);
}, 1000);
});
}
function processData(data) {
console.log(data.toUpperCase());
return 'Processed Data';
}
fetchData()
.then(processData)
.then(processedData => {
console.log(processedData); // 输出:Processed Data
})
.catch(error => {
console.error(error);
});
在以上示例中,Promise链式调用使得processData
函数可以接收上一个Promise的结果,并返回一个新的Promise。这样就可以实现一系列的异步操作。
async/await是ES8引入的语法糖,用于简化Promise的使用。通过async关键字定义的函数会返回一个Promise对象,而await关键字用于暂停异步代码的执行,等待Promise对象的解析。
示例使用async/await进行异步操作的代码:
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = 'Hello, World!';
resolve(data);
}, 1000);
});
}
async function processAsyncData() {
try {
const data = await fetchData();
console.log(data.toUpperCase()); // 输出:HELLO, WORLD!
return 'Processed Data';
} catch (error) {
console.error(error);
}
}
processAsyncData().then(processedData => {
console.log(processedData); // 输出:Processed Data
});
在以上示例中,使用await fetchData()
暂停了代码的执行,直到Promise对象fetchData()
解析为结果。然后可以像同步代码一样处理结果,并使用try-catch捕获错误。
调试是开发过程中非常重要的一部分,它可以帮助我们查找和修复代码中的错误。在Node.js应用开发中,有几种常见的调试方法:
使用console.log():最简单的调试方法是使用console.log()语句在代码中打印变量、状态或错误消息。这对于跟踪代码的执行流程和查看特定变量的值很有帮助。
使用Node.js内置的调试器:Node.js提供了一个内置的调试器工具,可以通过在终端中运行node inspect
命令来启动。这个调试器允许您在代码的任何位置设置断点,并在每个断点处停止执行,以便查看和修改变量的值。
使用第三方调试工具:除了Node.js内置的调试器外,还有一些第三方调试工具可供选择,例如Chrome DevTools、Visual Studio Code等。这些工具提供了更丰富的调试功能,如调试界面、可视化变量查看和代码跟踪等。
使用适当的开发工具可以大大提高开发效率。以下是一些常用的开发工具和技巧,特别是针对VS Code的:
代码编辑器:选择一款功能强大的代码编辑器,如Visual Studio Code(VS Code)。VS Code提供了丰富的功能和插件生态系统,可以加速开发流程。
插件和扩展:安装适用于您开发语言和框架的插件和扩展程序。例如,在VS Code中,您可以安装针对JavaScript和Node.js的插件,以增强代码补全、语法高亮和调试等功能。
快捷键和代码片段:学习使用快捷键和代码片段,可以显著提高编码速度和减少重复工作。VS Code支持自定义快捷键和代码片段,您可以根据自己的喜好进行配置。
版本控制集成:将您的项目与版本控制系统(如Git)集成,以便更好地跟踪和管理代码变更。VS Code具有与Git的无缝集成,并提供了许多有用的功能,如源代码比较、提交和推送等。
自动化测试是保证代码质量和功能正确性的重要手段。在Node.js应用开发中,以下是一些常见的自动化测试方法:
单元测试:单元测试是对代码中最小可测试单元(如函数、类)进行的测试。使用测试框架(如Mocha、Jest)编写和运行单元测试,以验证代码的各种情况下的行为是否符合预期。
集成测试:集成测试是对应用程序不同组件之间的集成进行的测试。它涉及到不同部分的协作,并确认其一起正常工作。使用工具(如Supertest、Puppeteer)编写和运行集成测试,以确保整个应用程序的功能正常。
代码覆盖率:代码覆盖率是度量测试用例对代码的覆盖程度的指标。它可以帮助您确定哪些部分的代码需要更多的测试。使用工具(如Istanbul)计算和报告代码覆盖率,以确保您的测试套件足够全面。
自动化测试和代码覆盖率工具可以帮助您提高代码质量并更快地发现错误。通过在开发过程中实施这些工具和实践,您可以减少手动测试的工作量,并提高应用程序的可维护性和稳定性。
在部署Node.js应用时,有几种常见的选择可供考虑:
传统服务器部署:将Node.js应用部署到传统的物理服务器或虚拟私有服务器(VPS)上。您可以使用工具(如SSH)远程连接到服务器,并在服务器上安装和配置Node.js环境,然后将应用程序部署到服务器中。
容器化部署:使用容器技术(如Docker)将Node.js应用打包成容器镜像,并在支持容器管理的平台上进行部署。容器化部署提供了更大的灵活性和可移植性,使得应用的交付和扩展更加容易。
无服务器部署:使用无服务器计算平台(如AWS Lambda、Google Cloud Functions)将Node.js应用部署为无状态函数。无服务器部署消除了对基础设施管理的需求,使得应用的部署和弹性伸缩更加简单。
性能优化是确保应用能够快速响应用户请求的关键。以下是一些常见的性能优化原则:
减少网络延迟:优化网络请求和响应,使用较低的延迟传输协议(如HTTP/2),合并和压缩资源,以减少网络传输时间。
前端优化:优化前端代码,减少不必要的重绘和回流,使用浏览器缓存和CDN来提高前端资源的加载速度。
数据库优化:合理设计数据库结构,使用索引、分区和缓存等技术来提高数据库查询的性能。
并发处理:使用异步编程模型(如Promise、async/await)来处理并发请求,避免阻塞和提高应用的吞吐量。
缓存、压缩和内容分发网络(CDN)是常用的性能优化技术:
缓存:使用缓存技术将经常访问的数据存储在内存或其他快速存储介质中,以避免重复的计算和数据库查询。Node.js中可以使用Redis或Memcached等缓存数据库。
压缩:通过对传输的数据进行压缩,减少数据的大小,从而降低网络传输时间。在Node.js中,您可以使用压缩中间件(如compression)来自动压缩响应。
CDN:使用内容分发网络(CDN)来缓存并分发静态资源,减少资源的加载时间和服务器的负载。CDN存储静态资源的副本,并将其分发到离用户最近的边缘节点。
水平扩展和负载均衡是处理大量并发请求的关键技术:
水平扩展:通过增加服务器实例数量来提高应用的处理能力。在Node.js中,可以使用负载均衡器(如Nginx、HAProxy)将用户请求分发到多个后端服务器上。
负载均衡:使用负载均衡算法来分发请求,以确保每个服务器都能获得相对均衡的负载。常见的负载均衡算法包括轮询、随机和最少连接等。
Node.js被广泛用于开发RESTful API,因为它具有轻量级和高性能的特点。以下是一些在Node.js中开发RESTful API的常见用例:
创建和管理用户:使用Node.js和框架(如Express、Koa)可以轻松地创建用户注册、登录和管理的API。
数据库操作:Node.js可以与各种数据库进行集成,如MongoDB、MySQL、PostgreSQL等。您可以使用Node.js编写API来执行数据库操作,例如插入、更新和查询数据。
身份验证和授权:使用Node.js和相关的库(如Passport.js)可以实现身份验证和授权机制,以确保只有经过授权的用户才能访问受保护的API端点。
Node.js适用于构建实时应用和聊天室,其中即时通信是一个关键需求。以下是Node.js在实时应用和聊天室中的应用示例:
即时通信:使用Socket.io等库,可以实现实时通信功能,例如即时聊天、实时通知和实时协作。Node.js的事件驱动模型使得处理大量并发连接成为可能。
多人聊天室:Node.js可以用于创建支持多人在线聊天的应用。通过使用WebSocket协议,可以实现用户之间的即时消息传递,并将其广播给所有在线用户。
Node.js也可用于处理批处理任务和定时器。以下是一些使用Node.js进行批处理和定时任务的示例:
数据处理:Node.js可以用于处理大量数据,例如读取文件、解析数据、转换格式等。利用Node.js的异步编程模型,可以高效地处理这些任务。
定时任务:使用Node.js的定时器功能,可以开发定时执行的任务,例如周期性地备份数据库、发送定期报告等。您可以使用Node.js的定时器库(如node-cron)来管理这些定时任务。
Node.js在数据采集和爬虫应用方面也具有很强的灵活性和高效性。以下是一些使用Node.js进行数据采集和爬虫的示例:
网络抓取:使用Node.js,您可以开发网络爬虫来抓取网页上的数据。通过HTTP请求库(如axios、request),您可以实现页面的下载和数据的提取。
数据清洗和分析:Node.js可以用于处理从不同来源采集的数据,进行清洗和加工,以便后续的数据分析和可视化。
Node.js在实际项目中有多种应用示例,包括RESTful API开发、实时应用和聊天室、批处理任务和定时器,以及数据采集和爬虫应用。这些示例只是Node.js应用的一小部分,您可以根据具体项目需求进一步扩展和定制。
Node.js是一个强大而灵活的服务器端JavaScript运行时环境,广泛应用于实际项目中。通过本文的讨论,我们可以得出以下结论和总结:
Node.js在RESTful API开发方面具有显著优势。其轻量级和高性能的特点使其成为构建快速、可扩展的API的理想选择。使用Node.js和相关框架,我们可以轻松地创建和管理用户、执行数据库操作以及实现身份验证和授权等功能。
实时应用和聊天室是Node.js的另一个重要应用领域。通过使用Socket.io等库,我们可以构建支持实时通信功能的应用,并实现即时聊天、实时通知和多人在线聊天等需求。
在批处理任务和定时器方面,Node.js可以处理大量并发任务,并通过使用定时器库来执行定时任务。这使得开发周期性的数据处理、报告生成和数据库备份等任务变得更加便捷。
数据采集和爬虫应用是Node.js的典型应用之一。利用Node.js的异步编程模型和网络请求库,我们可以轻松地开发网络爬虫来抓取网页上的数据,并进行数据清洗、分析和可视化等操作。
Node.js在实际项目中有着广泛的应用。通过使用Node.js,我们可以快速构建高性能的RESTful API,实现实时应用和聊天室,处理批处理任务和定时器,以及进行数据采集和爬虫应用。Node.js的优势在于其简单、快速且可扩展的特性,使得开发人员能够更好地满足各种项目需求。
文章浏览阅读8.6k次。一、Linux记录用户登录信息文件1 /var/run/utmp----记录当前正在登录系统的用户信息;2 /var/log/wtmp----记录当前正在登录和历史登录系统的用户信息;3 /var/log/btmp:记录失败的登录尝试信息。二、命令用法1.命令last,lastb---show a listing of la_怎么记录linux设备 发声的登录和登出
文章浏览阅读167次。摘要:1. 简介 2. 公园迷宫漫步 3. 无线迷宫与最短(不加权)路径问题 4. 强连通分量1. 简介在计算机科学裡,树的遍历(也称为树的搜索)是圖的遍歷的一种,指的是按照某种规则,不重复地访问某种樹的所有节点的过程。具体的访问操作可能是检查节点的值、更新节点的值等。不同的遍历方式,其访问节点的顺序是不一样的。两种著名的基本遍历策略:深度优先搜索(DFS) 和 广度优先搜索(B...
文章浏览阅读591次。提起报表,大家会觉得即熟悉又陌生,好像常常在工作中使用,又似乎无法准确描述报表。今天我们来一起了解一下什么是报表,报表的结构、构成元素,以及为什么需要报表。什么是报表简单的说:报表就是通过表格、图表等形式来动态显示数据,并为使用者提供浏览、打印、导出和分析的功能,可以用公式表示为:报表 = 多样的布局 + 动态的数据 + 丰富的输出报表通常包含以下组成部分:报表首页:在报表的开..._activereports.net 实现查询报表功能
文章浏览阅读6.6k次。最近实验室需要用Cadence,这个软件的安装非常麻烦,每一次配置都要几个小时,因此打算把Cadence装进Docker。但是Cadence运行时需要GUI,要对Docker进行一些配置。我们实验室的服务器运行的是Ubuntu18.04,默认桌面GNOME,Cadence装进Centos的Docker。安装Ubuntu18.04服务器上安装Ubuntu18.04的教程非常多,在此不赘述了安装..._docker xrdp ubuntu
文章浏览阅读1.8k次,点赞2次,收藏2次。首先导入头文件#import 导入头文件后创建几个相机必须实现的对象 /** * AVCaptureSession对象来执行输入设备和输出设备之间的数据传递 */ @property (nonatomic, strong) AVCaptureSession* session; /** * 输入设备 */_ios avcapturestillimageoutput 兼容性 ios17 崩溃
文章浏览阅读982次。按照OracleDocument中的描述,v$sysstat存储自数据库实例运行那刻起就开始累计全实例(instance-wide)的资源使用情况。 类似于v$sesstat,该视图存储下列的统计信息:1>.事件发生次数的统计(如:user commits)2>._oracle v$sysstat视图
文章浏览阅读7.6k次,点赞2次,收藏9次。我最近做SPA项目开发动态树的时候一直遇到以下错误:当我点击文章管理需要跳转路径时一直报NavigationDuplicated {_name: “NavigationDuplicated”, name: “NavigationDuplicated”}这个错误但是当我点击文章管理后,路径跳转却是成功的<template> <div> 文章管理页面 <..._navigationduplicated {_name: 'navigationduplicated', name: 'navigationduplic
文章浏览阅读3.9k次。版本VoiceEngine 4.1.0舒适噪音生成(comfort noise generator,CNG)是一个在通话过程中出现短暂静音时用来为电话通信产生背景噪声的程序。#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)static const EcModes kDefaultEcMode = kEcAecm;#elsestati..._webrtc aecm 杂音
文章浏览阅读6.3k次,点赞9次,收藏19次。医学成像原理与图像处理一:概论引言:本系列博客为医学成像原理与图像处理重要笔记,由于是手写,在此通过扫描录入以图片的形式和电子版增补内容将其进行组织和共享。前半部分内容为图像处理基础内容,包括图像的灰度级处理、空间域滤波、频率域滤波、图像增强和分割等;后半部分内容为医学影象技术,包括常规胶片X光机、CR、DR、CT、DSA等X射线摄影技术、超声成像技术、磁共振成像(MRI)技术等。本篇主要内容是概论。_医学成像与图像处理技术知识点总结
文章浏览阅读591次,点赞13次,收藏10次。notepad++ v8.5.3 安装插件,下载进度为0_nodepa++
文章浏览阅读2.1w次。用spark执行SQL保存到Hive中: hiveContext.sql("insert overwrite table test select * from aaa")执行完成,没报错,但是核对结果的时候,发现有几笔数据超出指定范围(实际只包含100/200)最终排查到是ret_pay_remark 字段包含换行符,解决方案:执行SQL中把特殊字符替换掉regexp_replace(..._hive sql \n
文章浏览阅读520次,点赞10次,收藏8次。印象笔记05:如何打造更美的印象笔记超级笔记本文介绍印象笔记的具体使用,如何打造更美更实用的笔记。首先想要笔记更加好看和实用,我认为要使用超级笔记。所谓超级笔记就是具有很多便捷功能的笔记。_好的印象笔记怎么做的