-
为更快的帮您定位问题,推荐您用以下模板反馈:1、出现问题时,您做了哪些操作?回答:npm install -g pnpm 2、在哪个步骤出现了问题?回答:codeArts1.0.10 pnpm安装 无rename权限? 3、您希望得到什么结果?回答:提示权限授权,或者给权限 4、您实际得到什么结果?回答:0 verbose cli /data/app/node.org/node_v24.11.1/bin/node /data/app/bin/npm1 info using npm@11.6.22 info using node@v24.11.13 silly config load:file:/data/app/node.org/node_v24.11.1/lib/node_modules/npm/npmrc4 silly config load:file:/storage/Users/currentUser/.npmrc5 silly config load:file:/data/storage/el2/base/files/npm_global_modules/etc/npmrc6 verbose title npm install pnpm7 verbose argv "install" "--global" "pnpm"8 verbose logfile logs-max:10 dir:/storage/Users/currentUser/.npm/_logs/2026-01-18T07_28_05_992Z-9 verbose logfile /storage/Users/currentUser/.npm/_logs/2026-01-18T07_28_05_992Z-debug-0.log10 silly packumentCache heap:4496293888 maxSize:1124073472 maxEntrySize:56203673611 silly logfile start cleaning logs, removing 1 files12 silly logfile done cleaning log files13 silly idealTree buildDeps14 silly fetch manifest pnpm@*15 silly packumentCache full:https://registry.npmmirror.com/pnpm cache-miss16 http fetch GET 200 https://registry.npmmirror.com/pnpm 371ms (cache miss)17 silly packumentCache full:https://registry.npmmirror.com/pnpm set size:621644 disposed:false18 silly placeDep ROOT pnpm@10.28.0 OK for: want: *19 silly reify mark retired [19 silly reify '/data/storage/el2/base/files/npm_global_modules/lib/node_modules/pnpm',19 silly reify '/data/storage/el2/base/files/npm_global_modules/bin/pnpm',19 silly reify '/data/storage/el2/base/files/npm_global_modules/bin/pnpx'19 silly reify ]20 silly reify moves {20 silly reify '/data/storage/el2/base/files/npm_global_modules/lib/node_modules/pnpm': '/data/storage/el2/base/files/npm_global_modules/lib/node_modules/.pnpm-6QfMcwHS',20 silly reify '/data/storage/el2/base/files/npm_global_modules/bin/pnpm': '/data/storage/el2/base/files/npm_global_modules/bin/.pnpm-X0jd3YlJ',20 silly reify '/data/storage/el2/base/files/npm_global_modules/bin/pnpx': '/data/storage/el2/base/files/npm_global_modules/bin/.pnpx-3g5kwIh1'20 silly reify }21 verbose stack Error: EACCES: permission denied, rename '/data/storage/el2/base/files/npm_global_modules/bin/pnpm' -> '/data/storage/el2/base/files/npm_global_modules/bin/.pnpm-X0jd3YlJ'21 verbose stack at async Object.rename (node:internal/fs/promises:787:10)21 verbose stack at async moveFile (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/node_modules/@npmcli/fs/lib/move-file.js:30:5)21 verbose stack at async Promise.allSettled (index 1)21 verbose stack at async [reifyPackages] (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js:313:11)21 verbose stack at async Arborist.reify (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js:125:5)21 verbose stack at async Install.exec (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/lib/commands/install.js:150:5)21 verbose stack at async Npm.exec (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/lib/npm.js:208:9)21 verbose stack at async module.exports (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/lib/cli/entry.js:67:5)22 error code EACCES23 error syscall rename24 error path /data/storage/el2/base/files/npm_global_modules/bin/pnpm25 error dest /data/storage/el2/base/files/npm_global_modules/bin/.pnpm-X0jd3YlJ26 error errno -1327 error Error: EACCES: permission denied, rename '/data/storage/el2/base/files/npm_global_modules/bin/pnpm' -> '/data/storage/el2/base/files/npm_global_modules/bin/.pnpm-X0jd3YlJ'27 error at async Object.rename (node:internal/fs/promises:787:10)27 error at async moveFile (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/node_modules/@npmcli/fs/lib/move-file.js:30:5)27 error at async Promise.allSettled (index 1)27 error at async [reifyPackages] (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js:313:11)27 error at async Arborist.reify (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js:125:5)27 error at async Install.exec (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/lib/commands/install.js:150:5)27 error at async Npm.exec (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/lib/npm.js:208:9)27 error at async module.exports (/data/app/node.org/node_v24.11.1/lib/node_modules/npm/lib/cli/entry.js:67:5) {27 error errno: -13,27 error code: 'EACCES',27 error syscall: 'rename',27 error path: '/data/storage/el2/base/files/npm_global_modules/bin/pnpm',27 error dest: '/data/storage/el2/base/files/npm_global_modules/bin/.pnpm-X0jd3YlJ'27 error }28 error28 error The operation was rejected by your operating system.28 error It is likely you do not have the permissions to access this file as the current user28 error28 error If you believe this might be a permissions issue, please double-check the28 error permissions of the file and its containing directories, or try running28 error the command again as root/Administrator.29 silly unfinished npm timer reify 176872128628530 silly unfinished npm timer reify:retireShallow 176872128676831 verbose cwd /storage/Users/currentUser/ucap-code/ucap-cloud-data-search32 verbose os HarmonyOS HongMeng Kernel 1.11.033 verbose node v24.11.134 verbose npm v11.6.235 verbose exit -1336 verbose code -1337 error A complete log of this run can be found in: /storage/Users/currentUser/.npm/_logs/2026-01-18T07_28_05_992Z-debug-0.log 5、出现故障的手机型号以及操作系统版本?回答: 6、集成的KIT的SDK的版本?回答: 7、请附上您出现问题页面的整屏截图;回答:8、如果您上传文件失败,请以附件形式提交您的文件。
-
方式三:使用nvm-windows安装首先请参考此处(cid:link_0)安装nvm-windows,然后执行如下命令安装对应的版本:nvm node_mirror https://mirrors.huaweicloud.com/nodejs/nvm npm_mirror https://mirrors.huaweicloud.com/npm-software/nvm install latestnvm use latest按照上面的方法设置后在CMD中执行 nvm install latest报错:Error retrieving "https://mirrors.huaweicloud.com/nodejs/latest/SHASUMS256.txt": HTTP Status 418各位大佬们,这个需要怎么解决呢?
-
launch.json文件launch.json 文件是 Visual Studio Code (VS Code) 中用于配置调试会话的文件。它定义了调试器如何启动和运行程序。以下是 launch.json 文件的详细配置说明,包括常见的属性及其用途。基本结构launch.json 文件通常位于 .vscode 目录下,具有以下基本结构:主要属性每个配置块代表一个调试配置,包含多个属性。以下是一些常见属性的说明:type: 调试器类型,如 python, cppdbg, node, java, 等。request: 调试请求类型,通常为 launch(启动)或 attach(附加)。name: 配置名称,用户可以在调试配置列表中看到。program: 要调试的程序路径或文件。args: 传递给程序的命令行参数,数组形式。cwd: 当前工作目录。env: 环境变量设置。sourceMaps: 是否启用源映射(通常用于 JavaScript 调试)。preLaunchTask: 调试前要执行的任务(通常用于编译等)。postDebugTask: 调试结束后要执行的任务。stopOnEntry: 是否在程序入口处停止。console: 控制台类型,如 integratedTerminal, externalTerminal, 或 internalConsole。justMyCode: 是否只调试用户代码(用于 Python)。pythonPath: Python 可执行文件的路径(用于 Python)。常见配置项1. Pythonprogram: 要调试的 Python 文件。pythonPath: Python 解释器路径。args: 传递给 Python 脚本的命令行参数。env: 环境变量。console: 控制台类型。2. C++program: 可执行文件路径。args: 命令行参数。stopAtEntry: 是否在程序入口处暂停。cwd: 当前工作目录。environment: 环境变量。externalConsole: 是否使用外部控制台。MIMode: 调试器模式(如 gdb, lldb)。miDebuggerPath: 调试器路径。3. Node.jsprogram: 要调试的 Node.js 文件。args: 命令行参数。runtimeExecutable: Node.js 可执行文件路径。runtimeArgs: 传递给 Node.js 的参数。env: 环境变量。sourceMaps: 是否启用源映射。outFiles: 编译输出文件路径。tasks.jsontasks.json 文件是 Visual Studio Code (VS Code) 中用于配置任务(Tasks)的文件。这些任务可以是编译代码、运行测试、构建项目等自动化任务。以下是 tasks.json 文件的详细配置说明,包括常见的属性及其用途。主要属性每个任务配置块代表一个任务,包含多个属性。以下是一些常见属性的说明:label: 任务的名称或标签,用于在任务列表中标识任务。type: 任务类型,例如 shell 或 process。shell 表示任务将在 shell 中运行,process 表示任务将作为独立的进程运行。command: 要执行的命令,可以是编译器、构建工具、脚本等。args: 传递给命令的参数,数组形式。group: 任务分组,可以设置为 build 或 test,用于标识构建任务或测试任务。presentation: 控制任务输出的呈现方式,例如是否显示在终端中,是否清除之前的输出等。problemMatcher: 配置错误和警告的匹配器,用于从任务输出中解析错误和警告。options: 任务执行的选项,例如环境变量、当前工作目录等。常见配置项label任务的标签名称,用于在 VS Code 任务列表中标识任务。1"label": "build"type任务类型,可以是 shell 或 process。shell 表示任务将在 shell 中运行,process 表示任务将作为独立的进程运行。1"type": "shell"command要执行的命令,例如编译器、脚本或构建工具。1"command": "g++"args传递给命令的参数,数组形式。123456"args": [ "-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}.out"]group任务分组,用于标识任务的类别,可以是 build 或 test。1234"group": { "kind": "build", "isDefault": true}presentation控制任务输出的呈现方式。123456"presentation": { "echo": true, "reveal": "always", "focus": false, "panel": "shared"}problemMatcher用于解析任务输出中的错误和警告。VS Code 内置了多种匹配器,例如 $gcc, $eslint 等。1"problemMatcher": ["$gcc"]options任务执行的选项,例如环境变量、当前工作目录等。
-
最近在维护一个小后台项目,有段JS需要压缩上传到CDN存储服务器。由于之前压缩的JS文件都比较少,都是手动压缩的。这次需要压缩的文件比较多,所以用了批量压缩。特此记录一下,方便大家和自己以后再用到的时候备忘。回到顶部v准备工作安装nodejs首先在本地安装node.js和npm,一般npm集成于nodejs,即安装nodejs,同时也安装了npm。node.js下载地址,下载以后直接不停下一步就行,全部使用默认选项即可。下载完成后打开CMD,node -v检测是否安装成功,安装成功则会显示nodejs版本号。安装uglify插件在cmd命令行执行:npm install uglify-js -g回到顶部v开始压缩压缩的时候将下面的代码拷贝下来,然后生成bat文件,再运行bat文件(有些电脑可能需要windows管理员身份运行),然后依次输入当前的JS文件目录。再输入生成输出压缩后JS的目录即可。@ECHO OFF setlocal enabledelayedexpansion set source_path=%1 set target_dir=%2 IF [%1]==[] ( rem echo please input javascript file or directory set /p source_path=please input javascript file or directory: ) IF [%2]==[] ( rem echo please input output directory set /p target_dir=please input output directory: ) rem source path exists? FOR %%i IN (%source_path%) DO SET FileAttrib=%%~ai if "%FileAttrib%" equ "" ( rem not found file attribute, source path not exist echo source path ^(%source_path%^) doesn't exist exit /b 0 ) ELSE IF "%FileAttrib:~0,1%" equ "d" ( rem source path is directory and not end with \, append \ to source path IF %source_path:~-1% neq \ ( set source_path=%source_path%\ ) ) echo source path is %source_path% rem target path exists? FOR %%i IN (%target_dir%) DO SET fa=%%~ai IF [%fa%]==[] ( rem target path not exist, make it mkdir %target_dir% ) IF %target_dir:~-1% neq \ ( rem append \ to target path set target_dir=%target_dir%\ ) echo target path is %target_dir% IF [%FileAttrib:~0,1%]==[d] ( for /r %source_path% %%I in (*.js) do ( set file_name=%%~nI set parent=%%~dpI set target_parent=%target_dir%!parent:%source_path%=! if not exist !target_parent! mkdir !target_parent! cd !target_parent! if [!file_name:~-4!] neq [.min] ( set w= uglifyjs %%I -m -c -O ascii_only=true -o !target_parent!%%~nI.min.js rem uglify .js file echo uglifyjs from "%%I" to "!target_parent!%%~nI.min.js" start cmd /c "!w!" ) else ( rem copy min.js file echo copy file from "%%~dpnI.js" to "!target_parent!%%~nI.js" start cmd /c "copy %%~dpnI.js !target_parent!%%~nI.js" ) ) ) else ( for %%I in (%source_path%) do ( IF "%%~xI" EQU ".js" ( set file_name=%%~nI if [!file_name:~-4!] neq [.min] ( rem uglify .js file set val=%target_dir%%%~nI.min.js echo uglifyjs from "%%I" to "!val!" start cmd /c "uglifyjs %%I -m -c -O ascii_only=true -o !val!" ) else ( rem copy min.js file echo copy file from "%%I" to "%target_dir%%%~nI.js" start cmd /c "copy %%I %target_dir%%%~nI.js" ) ) ) ) echo done
-
起因很多人都知道,setTimeout是有最小延迟时间的,根据MDN 文档 setTimeout:实际延时比设定值更久的原因:最小延迟时间中所说:在浏览器中,setTimeout()/setInterval() 的每调用一次定时器的最小间隔是 4ms,这通常是由于函数嵌套导致(嵌套层级达到一定深度)。在HTML Standard规范中也有提到更具体的:Timers can be nested; after five such nested timers, however, the interval is forced to be at least four milliseconds.简单来说,5 层以上的定时器嵌套会导致至少 4ms 的延迟。用如下代码做个测试:12345678910111213141516171819202122232425let a = performance.now();setTimeout(() => { let b = performance.now(); console.log(b - a); setTimeout(() => { let c = performance.now(); console.log(c - b); setTimeout(() => { let d = performance.now(); console.log(d - c); setTimeout(() => { let e = performance.now(); console.log(e - d); setTimeout(() => { let f = performance.now(); console.log(f - e); setTimeout(() => { let g = performance.now(); console.log(g - f); }, 0); }, 0); }, 0); }, 0); }, 0);}, 0);在浏览器中的打印结果大概是这样的,和规范一致,第五次执行的时候延迟来到了 4ms 以上。探索假设就需要一个「立刻执行」的定时器呢?有什么办法绕过这个 4ms 的延迟吗,在 MDN 文档的角落里有一些线索:如果想在浏览器中实现 0ms 延时的定时器,可以参考这里所说的window.postMessage()。这篇文章里的作者给出了这样一段代码,用postMessage来实现真正 0 延迟的定时器:12345678910111213141516171819202122232425(function () { var timeouts = []; var messageName = 'zero-timeout-message'; // 保持 setTimeout 的形态,只接受单个函数的参数,延迟始终为 0。 function setZeroTimeout(fn) { timeouts.push(fn); window.postMessage(messageName, '*'); } function handleMessage(event) { if (event.source == window && event.data == messageName) { event.stopPropagation(); if (timeouts.length > 0) { var fn = timeouts.shift(); fn(); } } } window.addEventListener('message', handleMessage, true); // 把 API 添加到 window 对象上 window.setZeroTimeout = setZeroTimeout;})();由于postMessage的回调函数的执行时机和setTimeout类似,都属于宏任务,所以可以简单利用postMessage和addEventListener('message')的消息通知组合,来实现模拟定时器的功能。这样,执行时机类似,但是延迟更小的定时器就完成了。再利用上面的嵌套定时器的例子来跑一下测试:全部在 0.1 ~ 0.3 毫秒级别,而且不会随着嵌套层数的增多而增加延迟。测试从理论上来说,由于postMessage的实现没有被浏览器引擎限制速度,一定是比 setTimeout 要快的。设计一个实验方法,就是分别用postMessage版定时器和传统定时器做一个递归执行计数函数的操作,看看同样计数到 100 分别需要花多少时间。实验代码:1234567891011121314151617181920212223242526272829303132333435363738394041424344function runtest() { var output = document.getElementById('output'); var outputText = document.createTextNode(''); output.appendChild(outputText); function printOutput(line) { outputText.data += line + '\n'; } var i = 0; var startTime = Date.now(); // 通过递归 setZeroTimeout 达到 100 计数 // 达到 100 后切换成 setTimeout 来实验 function test1() { if (++i == 100) { var endTime = Date.now(); printOutput( '100 iterations of setZeroTimeout took ' + (endTime - startTime) + ' milliseconds.' ); i = 0; startTime = Date.now(); setTimeout(test2, 0); } else { setZeroTimeout(test1); } } setZeroTimeout(test1); // 通过递归 setTimeout 达到 100 计数 function test2() { if (++i == 100) { var endTime = Date.now(); printOutput( '100 iterations of setTimeout(0) took ' + (endTime - startTime) + ' milliseconds.' ); } else { setTimeout(test2, 0); } }}实验代码很简单,先通过setZeroTimeout也就是postMessage版本来递归计数到 100,然后切换成 setTimeout计数到 100。直接放结论,这个差距不固定,在 mac 上用无痕模式排除插件等因素的干扰后,以计数到 100 为例,大概有 80 ~ 100 倍的时间差距。在硬件更好的台式机上,甚至能到 200 倍以上。Performance 面板只是看冷冰冰的数字还不够过瘾,打开 Performance 面板,看看更直观的可视化界面中,postMessage版的定时器和setTimeout版的定时器是如何分布的。这张分布图非常直观的体现出了上面所说的所有现象,左边的postMessage版本的定时器分布非常密集,大概在 5ms 以内就执行完了所有的计数任务。而右边的setTimeout版本相比较下分布的就很稀疏了,而且通过上方的时间轴可以看出,前四次的执行间隔大概在 1ms 左右,到了第五次就拉开到 4ms 以上。作用也许有同学会问,有什么场景需要无延迟的定时器?其实在 React 的源码中,做时间切片的部分就用到了。12345678910111213141516171819const channel = new MessageChannel();const port = channel.port2;// 每次 port.postMessage() 调用就会添加一个宏任务// 该宏任务为调用 scheduler.scheduleTask 方法channel.port1.onmessage = scheduler.scheduleTask;const scheduler = { scheduleTask() { // 挑选一个任务并执行 const task = pickTask(); const continuousTask = task(); // 如果当前任务未完成,则在下个宏任务继续执行 if (continuousTask) { port.postMessage(null); } },};React 把任务切分成很多片段,这样就可以通过把任务交给postMessage的回调函数,来让浏览器主线程拿回控制权,进行一些更优先的渲染任务(比如用户输入)。为什么不用执行时机更靠前的微任务呢?关键的原因在于微任务会在渲染之前执行,这样就算浏览器有紧急的渲染任务,也得等微任务执行完才能渲染。总结可以了解如下几个知识点:setTimeout的 4ms 延迟历史原因,具体表现。如何通过postMessage实现一个真正 0 延迟的定时器。postMessage定时器在 React 时间切片中的运用。为什么时间切片需要用宏任务,而不是微任务。本文转载于:https://juejin.cn/post/7229520942668824633
-
Node.js 团队近期新发布20.6.0版本,在今年4月的版本上增强了安全性和API引入,同时也增加对新操作系统的支持以及对 TypeScript 兼容性的优化,虽然现在该版本处于测试阶段,你觉得Node.js在未来会呈现怎样的发展态势呢?Node.js新版本发布,你觉得哪一性能提升最实用?你觉得Node.js与JAVA相比,其优势在哪里?未来会超越JAVA吗?
-
最近项目中要用到node写接口然后连接公司现有的sql.server数据库,再把执行结果返回给前端(还是我),因为之前一直做前端这块,后端这方面不是很懂,花了很长的时间终于研究出来了(还是太菜了,走了很多弯路),所以写个博客,一是复习巩固,二是给其他有需要的小伙伴一个参考,尽量少走弯路,废话不多说,直接上代码 1.首先在自己的数据库新建一张表,用于接下来的测试 2.在自己的项目文件夹中建两个文件,config.js & mssql.js 3.封装数据库信息,config.js //config.js let app = { user: 'xxxxxx', //这里写你的数据库的用户名 password: 'xxxxxx',//这里写数据库的密码 server: 'localhost', database: 'testDB', // 数据库名字 port: 1433, //端口号,默认1433 options: { encrypt: false, //加密,设置为true时会连接失败 Failed to connect to localhost:1433 - self signed certificate enableArithAbort: false }, pool: { min: 0, max: 10, idleTimeoutMillis: 3000 } } module.exports = app 4.对sql语句的二次封装 , mssql.js //mssql.js /** *sqlserver Model **/ const mssql = require("mssql"); const conf = require("./config.js"); const pool = new mssql.ConnectionPool(conf) const poolConnect = pool.connect() pool.on('error', err => { console.log('error: ', err) }) /** * 自由查询 * @param sql sql语句,例如: 'select * from news where id = @id' * @param params 参数,用来解释sql中的@*,例如: { id: id } * @param callBack 回调函数 */ let querySql = async function (sql, params, callBack) { try { let ps = new mssql.PreparedStatement(await poolConnect); if (params != "") { for (let index in params) { if (typeof params[index] == "number") { ps.input(index, mssql.Int); } else if (typeof params[index] == "string") { ps.input(index, mssql.NVarChar); } } } ps.prepare(sql, function (err) { if (err) console.log(err); ps.execute(params, function (err, recordset) { callBack(err, recordset); ps.unprepare(function (err) { if (err) console.log(err); }); }); }); } catch (e) { console.log(e) } }; /** * 按条件和需求查询指定表 * @param tableName 数据库表名,例:'news' * @param topNumber 只查询前几个数据,可为空,为空表示查询所有 * @param whereSql 条件语句,例:'where id = @id' * @param params 参数,用来解释sql中的@*,例如: { id: id } * @param orderSql 排序语句,例:'order by created_date' * @param callBack 回调函数 */ let select = async function (tableName, topNumber, whereSql, params, orderSql, callBack) { try { let ps = new mssql.PreparedStatement(await poolConnect); let sql = "select * from " + tableName + " "; if (topNumber != "") { sql = "select top(" + topNumber + ") * from " + tableName + " "; } sql += whereSql + " "; if (params != "") { for (let index in params) { if (typeof params[index] == "number") { ps.input(index, mssql.Int); } else if (typeof params[index] == "string") { ps.input(index, mssql.NVarChar); } } } sql += orderSql; console.log(sql); ps.prepare(sql, function (err) { if (err) console.log(err); ps.execute(params, function (err, recordset) { callBack(err, recordset); ps.unprepare(function (err) { if (err) console.log(err); }); }); }); } catch (e) { console.log(e) } }; /** * 查询指定表的所有数据 * @param tableName 数据库表名 * @param callBack 回调函数 */ let selectAll = async function (tableName, callBack) { try { let ps = new mssql.PreparedStatement(await poolConnect); let sql = "select * from " + tableName + " "; ps.prepare(sql, function (err) { if (err) console.log(err); ps.execute("", function (err, recordset) { callBack(err, recordset); ps.unprepare(function (err) { if (err) console.log(err); }); }); }); } catch (e) { console.log(e) } }; /** * 添加字段到指定表 * @param addObj 需要添加的对象字段,例:{ name: 'name', age: 20 } * @param tableName 数据库表名 * @param callBack 回调函数 */ let add = async function (addObj, tableName, callBack) { try { let ps = new mssql.PreparedStatement(await poolConnect); let sql = "insert into " + tableName + "("; if (addObj != "") { for (let index in addObj) { if (typeof addObj[index] == "number") { ps.input(index, mssql.Int); } else if (typeof addObj[index] == "string") { ps.input(index, mssql.NVarChar); } sql += index + ","; } sql = sql.substring(0, sql.length - 1) + ") values("; for (let index in addObj) { if (typeof addObj[index] == "number") { sql += addObj[index] + ","; } else if (typeof addObj[index] == "string") { sql += "'" + addObj[index] + "'" + ","; } } } sql = sql.substring(0, sql.length - 1) + ") SELECT @@IDENTITY id"; // 加上SELECT @@IDENTITY id才会返回id ps.prepare(sql, function (err) { if (err) console.log(err); ps.execute(addObj, function (err, recordset) { callBack(err, recordset); ps.unprepare(function (err) { if (err) console.log(err); }); }); }); } catch (e) { console.log(e) } }; /** * 更新指定表的数据 * @param updateObj 需要更新的对象字段,例:{ name: 'name', age: 20 } * @param whereObj 需要更新的条件,例: { id: id } * @param tableName 数据库表名 * @param callBack 回调函数 */ let update = async function (updateObj, whereObj, tableName, callBack) { try { let ps = new mssql.PreparedStatement(await poolConnect); let sql = "update " + tableName + " set "; if (updateObj != "") { for (let index in updateObj) { if (typeof updateObj[index] == "number") { ps.input(index, mssql.Int); sql += index + "=" + updateObj[index] + ","; } else if (typeof updateObj[index] == "string") { ps.input(index, mssql.NVarChar); sql += index + "=" + "'" + updateObj[index] + "'" + ","; } } } sql = sql.substring(0, sql.length - 1) + " where "; if (whereObj != "") { for (let index in whereObj) { if (typeof whereObj[index] == "number") { ps.input(index, mssql.Int); sql += index + "=" + whereObj[index] + " and "; } else if (typeof whereObj[index] == "string") { ps.input(index, mssql.NVarChar); sql += index + "=" + "'" + whereObj[index] + "'" + " and "; } } } sql = sql.substring(0, sql.length - 5); ps.prepare(sql, function (err) { if (err) console.log(err); ps.execute(updateObj, function (err, recordset) { callBack(err, recordset); ps.unprepare(function (err) { if (err) console.log(err); }); }); }); } catch (e) { console.log(e) } }; /** * 删除指定表字段 * @param whereSql 要删除字段的条件语句,例:'where id = @id' * @param params 参数,用来解释sql中的@*,例如: { id: id } * @param tableName 数据库表名 * @param callBack 回调函数 */ let del = async function (whereSql, params, tableName, callBack) { try { let ps = new mssql.PreparedStatement(await poolConnect); let sql = "delete from " + tableName + " "; if (params != "") { for (let index in params) { if (typeof params[index] == "number") { ps.input(index, mssql.Int); } else if (typeof params[index] == "string") { ps.input(index, mssql.NVarChar); } } } sql += whereSql; ps.prepare(sql, function (err) { if (err) console.log(err); ps.execute(params, function (err, recordset) { callBack(err, recordset); ps.unprepare(function (err) { if (err) console.log(err); }); }); }); } catch (e) { console.log(e) } }; exports.config = conf; exports.del = del; exports.select = select; exports.update = update; exports.querySql = querySql; exports.selectAll = selectAll; exports.add = add; 5.接口代码,api/user.js //user.js const express = require('express'); const db = require('../utils/mssql.js'); const moment = require('moment'); const router = express.Router(); /* GET home page. */ router.get('/info', function (req, res, next) { db.selectAll('userInfo', function (err, result) {//查询所有userInfo表的数据 res.send(result.recordset) // res.render('userInfo', { results: result.recordset, moment: moment }); }); }); router.post('/delete', function (req, res, next) {//删除一条id对应的userInfo表的数据 console.log(req.body, 77); const { UserId } = req.body const id = UserId db.del("where id = @id", { id: id }, "userInfo", function (err, result) { console.log(result, 66); res.send('ok') }); }); router.post('/update/:id', function (req, res, next) {//更新一条对应id的userInfo表的数据 var id = req.params.id; var content = req.body.content; db.update({ content: content }, { id: id }, "userInfo", function (err, result) { res.redirect('back'); }); }); module.exports = router; 6.启动文件,server.js //1.导入模块 const express = require('express') //2.创建服务器 let server = express() server.use(express.urlencoded()) //中间件要写在启动文件里面 const cors = require('cors') server.use(cors()) const user = require('./api/user.js') server.use('/', user) //3.开启服务器 server.listen(8002, () => { console.log('服务器已启动,在端口号8002') }) 7.启动服务器 8.用postman测试接口 数据成功返回~~~ ———————————————— 版权声明:本文为CSDN博主「快乐的小鱼儿12」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/m0_67296095/article/details/126326217
-
在Node.JS中使用多进程非常简单,合理使用多进程,可以解放硬件的能力,让软件的运行效率得到肉眼可见的提升。本文详细讲解了Node.js使用多进程提高任务执行效率的方法,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下最近我有个学员写了个 Node.js 脚本程序,定时从某个服务器下载文件,并向另一个云服务商上传文件。但是每次只能先下载一个文件,再去上传一个文件。效率比较低。于是他向我请教,怎么样才能提高效率?我告诉他应该用 Node 的多进程技术。什么是 Node 多进程?Node 是在单个线程中运行,我们虽然没办法开启额外的线程,但是可以开启进程集群。这样可以让下载任务和上传任务同时进行。使用多进程进行初步代码优化简单看了一下学员的代码,大概是这样:123456789101112const dl = require('./download.js')const ul = require('./upload.js')const source = require('./source.js')async function runTask() { const { originUrl, targetUrl } = source.getNext() const { data } = await dl(originUrl) await ul(targetUrl, data) runTask()}runTask()这个代码逻辑上是没问题的,但是它只能在 1 个 CPU 核心中运行。我们完全可以使用 Node.js 的多进程来利用 CPU 的多核心来增加这个程序的吞吐量。怎么改造呢?也非常简单。1234567891011121314151617181920212223242526const os = require('os')const cluster = require('cluster')const dl = require('./download.js')const ul = require('./upload.js')const source = require('./source.js')function run() { if(cluster.isMaster) { const numCPUs = os.cpus().length; for(let idx = 0; idx < numCPUs; idx++) { cluster.fork(); } } else { runTask() }}async function runTask() { const { originUrl, targetUrl } = source.getNext() const { data } = await dl(originUrl) await ul(targetUrl, data) runTask() }}run()在上面的代码中,我添加了 os 和 cluster 模块。os 模块可以告诉我们运行环境的 CPU 信息,我们可以通过它来做为创建进程数量的限制条件。然后通过 cluster.isMaster 来判断是否是主进程,因为只有主进程才拥有 fork 的能力。worker和master通信其实上面的代码还可以继续做更深层次的优化,仔细分析一下,下载速度和上传速度其实是不一致的。通常来说,下载速度会很慢,但上传速度会很快。我们可以让其他进程去下载文件,当下载成功之后,让主进程去上传文件。Node 中的多进程之间不会共享内存,所以我们可以通过消息传递的方式,让下载进程通知主进程去上传文件。12345678910111213141516171819202122232425262728const os = require('os')const cluster = require('cluster')const dl = require('./download.js')const ul = require('./upload.js')const source = require('./source.js')function run() { if(cluster.isMaster) { const numCPUs = os.cpus().length; for(let idx = 0; idx < numCPUs; idx++) { const worker = cluster.fork(); worker.on('message', ({ targetUrl, data }) => { ul(targetUrl, data) }) } } else { runTask() }}async function runTask() { const { originUrl, targetUrl } = source.getNext() const { data } = await dl(originUrl) process.send({ targetUrl, data }) runTask()}run()可以在主进程中通过 worker.on('message', (msg)=>{}) 的方式来监听子进程发送的消息。在子进程中通过 process.send 来向主进程发送消息。总结在 NodeJS 中使用多进程非常简单,合理使用多进程,可以解放硬件的能力,让软件的运行效率得到肉眼可见的提升。转载自https://www.jb51.net/article/263647.htm
-
Node.js前端工程在arm机器安装依赖时出现很多前端组件找不到arm版的问题,很多依赖不兼容arm,请问是否有arm版本的前端组件库?
-
今天新启动一个项目,在 npm install 安装依赖项时出现报错,所以下面这篇文章主要给大家介绍了关于npm install安装报错:gyp info it worked if it ends with ok的解决方法,需要的朋友可以参考下目录• 1.可能原因1:node和node-sass版本冲突, • 2.node.js卸载与安装 • 3.node-sass卸载安装, • 4.安装好后对应版本的node和node-sass后启动 • 总结 前端vue新项目 npm install安装报错 gyp info it worked if it ends with ok1.可能原因1:node和node-sass版本冲突,对应的node和node-sass的版本如下2.node.js卸载与安装之前有安装过弄过node.js的如果node.js版本过高需要重新安装低版本node.js,在控制面板卸载node.js,再在node官网 下载对应的msi包安装到之前的安装过node.js的文件夹下。低版本的node.js 只需直接下载高版本的msi包安装无需卸载之前的低版本node.js,这样不需要再去配置环境变量啥的,3.node-sass卸载安装,node-sass卸载:1npm uninstall node-sassnode-sass安装可以指定版本:npm install node-sass 布置的版本直接安装npm install node-sass@4.14.0 指定4.14版本的,如果安装报错试试换下淘宝镜像,一个好的解决方案在是直接在项目根目录下创建一个 .npmrc文件指定淘宝镜像文件内容:sass_binary_site=https://npm.taobao.org/mirrors/node-sass/ phantomjs_cdnurl=https://npm.taobao.org/mirrors/phantomjs/ electron_mirror=https://npm.taobao.org/mirrors/electron/ registry=https://registry.npm.taobao.org4.安装好后对应版本的node和node-sass后启动再npm install , npm run dev 没有报错啦总结到此这篇关于npm install安装报错:gyp info it worked if it ends with ok解决的文章就介绍到这了转载自https://www.jb51.net/article/255441.htm
-
原文链接:https://blog.csdn.net/mengyidan/article/details/122947823在昨日的情人节当天,OpenJS基金会为保证JavaScript开源社区的持续增长,正式宣布收购Node.js徽标和商标的所有权。即日起,为Node.js提供长期赞助与管理的Joyent公司将把Node.js商标的所有权与管理权转让给OpenJS基金会,后者将负责Node.js的商标管理与维护工作。图源:OpenJS基金会官网Node.js是基于Chrome 的V8 JavaScript 引擎构建的JavaScript 运行时,由美国软件工程师瑞安·达尔开发。起初,Node.js的开发和维护工作是由达尔主持,其当时所在的公司Joyen提供赞助,随后达尔离开,Node.js社区也经历了一些分支与合并事件。目前Node.js有OpenJS基金会持有和维护,当下的最新版本为Node.js 17.5.0,其中LTS版本为Node.js 16.14.0。Node.js官网:https://nodejs.org/en/其实在6年前,OpenJS基金会已经获得了Node.js商标的免费永久许可使用权,包括那个六边形图形,商标转让并不会对贡献者产生任何影响。就开源产品而言,商标不仅可以保护开源项目,还能识别代码的具体来源。据OpenJS官博介绍,他们的目标是确保OpenJS商标政策在法律上尽可能的灵活和容易理解,同时保证Node.js以及OpenJS其它产品的服务和质量。Joyent总裁兼首席运营官Sung Whan Moon也表示,Joyent一直相信开源能给开发者和企业创造更多机会,很高兴能看到Node.js为这么多开发者、企业的经济增长带来支撑。随着Node.js进入第2个十年,把它放在一个中立的、并且在需要时能够制定商标限制,充分保证了项目的完整性,OpenJS基金会会是Node.js商标所有权的最佳容身之处。Node.js作为一个健康社区,得到了许多公司的广泛支持,这些公司扩大了这个项目的规模和商业应用,包括彭博社、美国国家航空航天局、Netflix等等。Node.js刚刚交付了Node.js 17,并将Node.js 16移至长期支持(LTS)。Joyent商业集团负责人和OpenJS董事会白金董事Sean Johnson提到,Node.js的采用前景将比以往任何时候都要光明。IBM开放技术和开发者倡导副总裁、OpenJS基金会董事会主席Todd Moore表示,"就推动JavaScript技术的广泛采用以及关键Node.js解决方案和相关技术的持续发展的使命,OpenJS基金会已经做好了准备。"Node.js的维护者们也正在为Node.js未来十年的战略方向进行合作。关于OpenJS基金会OpenJS基金会致力于支持JavaScript生态系统和网络技术的健康发展,提供一个中立的组织来主持和维持项目,并为整个社区的利益合作资助活动。OpenJS基金会由38个开源JavaScript项目组成,包括Appium、Dojo、jQuery、Node.js和webpack,并得到30个企业和最终用户成员的支持,包括GoDaddy、Google、IBM、Intel、Joyent和Microsoft。这些成员认识到JavaScript生态系统的相互关联性,以及为代表重大共享价值的项目提供一个中央家园的重要性。关于Linux基金会Linux基金会成立于2000年,由1000多个成员支持,是世界上领先的开源软件、开放标准和开放硬件的合作之家。Linux基金会的项目,如Linux、Kubernetes、Node.js等,被认为对世界上最重要的基础设施的发展至关重要。其开发方法利用既定的最佳实践,并解决贡献者、用户和解决方案提供者的需求,以创造可持续的开放合作模式。
-
>摘要: 网络是通信互联的基础,Node.js提供了net、http、dgram等模块,分别用来实现TCP、HTTP、UDP的通信,本文主要对使用Node.js的TCP通信部份进行实践记录。本文分享自华为云社区[《一文搞懂如何使用Node.js进行TCP网络通信》](https://bbs.huaweicloud.com/blogs/300544?utm_source=zhihu&utm_medium=bbs-ex&utm_campaign=other&utm_content=content),作者:lwq1228 。 # 1、构建TCP服务器 ## 1.1、使用Node.js创建TCP服务器 为了使用Node.js创建TCP服务器,首先要调用require(‘net’)来加载net模块,然后调用net模块的createServer方法就可以轻松地创建一个TCP服务器,语法格式如下: net.createServer([options][, connectionListener]) options是一个对象参数值,有两个布尔类型的属性allowHalfOpen和pauseOnConnect。这两个属性默认都是false; connectionListener是一个当客户端与服务端建立连接时的回调函数,这个回调函数以socket端口对象作为参数。 ## 1.2、监听客户端的连接 使用TCP服务器的listen方法就可以开始监听客户端的连接,语法格式如下: server.listen(port[, host][, backlog][, callback]); port:为需要监听的端口号,参数值为0的时候将随机分配一个端口号; host:服务器地址; backlog:连接等待队列的最大长度; callback:回调函数。 以下代码可以创建一个TCP服务器并监听8001端口: //引入net模块 const net = require('net'); //创建TCP服务器 const server = net.createServer(function (socket) { console.log('有新的客户端接入'); }); //设置监听端口 server.listen(8001, function () { console.log('服务正在监听中。。。') }); 运行这段代码,可以在控制台看到执行了listen方法的回调函数,如图所示:  可以使用相应的TCP客户端或者调试工具来连接这个已经创建好的TCP服务器。例如,要使用Windows的Telnet就可以用以下命令来连接: `telnet localhost 8001` 连接成功后可以看到控制台打印了“有新的客户端接入”字样,表明createServer方法的回调函数已经执行,说明已经成功连接到这个创建好的TCP服务器。  server.listen()方法其实触发的是server下的listening事件,所以也可以手动监听listening事件,代码如下: //设置监听端口 server.listen(8001); //设置监听时的回调函数 server.on('listening', function () { console.log("服务正在监听中。。。") }); 除了listening事件外,TCP服务器还支持以下事件: connection:当有新的链接创建时触发,回调函数的参数为socket连接对象。 close:TCP服务器关闭的时候触发,回调函数没有参数。 error:TCP服务器发生错误的时候触发,回调函数的参数为error对象。 下列代码通过net.Server类来创建一个TCP服务器,添加以上事件: //引入net模块 const net = require('net'); //实例化一个服务器对象 const server = new net.Server(); //监听connection事件 server.on('connection', function (socket) { console.log('有新的客户端接入'); }); //设置监听端口 server.listen(8001); //设置监听时的回调函数 server.on('listening', function () { console.log('服务正在监听中。。。'); }); //设置关闭时的回调函数 server.on('close', function () { console.log('服务已关闭'); }); //设置出错时的回调函数 server.on('error', function (err) { console.log('服务运行异常', err); }); ## 1.3、查看服务器监听的地址 当创建了一个TCP服务器后,可以通过server.address()方法来查看这个TCP服务器监听的地址,并返回一个JSON对象,因为这个方法返回的是TCP服务器监听的地址信息,所以应该在调用了server.listen()方法或者绑定了事件listening中的回调函数中调用该方法。这个对象的属性有: port:TCP服务器监听的端口号; family:说明TCP服务器监听的地址是IPv6还是IPv4; address:TCP服务器监听的地址。 代码如下: //引入net模块 const net = require('net'); //创建TCP服务器 const server = net.createServer(function (socket) { console.log('有新的客户端接入'); }); //设置监听端口 server.listen(8001); //设置监听时的回调函数 server.on('listening', function () { //获取地址信息 let address = server.address(); //获取地址详细信息 console.log("服务器监听的端口是:" + address.port); console.log("服务器监听的地址是:" + address.address); console.log("服务器监听的地址类型是:" + address.family); }); 运行结果如图:  ## 1.4、连接服务器的客户端数量 创建一个TCP服务器后,可以通过server.getConnections()方法获取连接这个TCP服务器的客户端数量。这个方法是一个异步的方法,回调函数有两个参数: 第一个参数为error对象。 第二个参数为连接TCP服务器的客户端数量。 除了获取连接数外,也可以通过设置TCP服务器的maxConnections属性来设置这个TCP服务器的最大连接数。当连接数超过最大连接数的时候,服务器将拒绝新的连接。如下代码设置这个TCP服务器的最大连接数为3。 //引入net模块 const net = require('net'); //创建TCP服务器 const server = net.createServer(function (socket) { console.log('有新的客户端接入'); //设置最大连接数量 server.maxConnections = 3; server.getConnections(function (err, count) { console.log("当前连接的客户端个数为:" + count); }); }); //设置监听端口 server.listen(8001, function () { console.log("服务正在监听中。。。") }); 运行这段代码,并尝试用多个客户端连接。可以发现当客户端连接数超过3的时候,新的客户端就无法连接这个服务器了,如图所示:  1.5、获取客户端发送的数据 createServer方法的回调函数参数是一个net.Socket对象(服务器所监听的端口对象),这个对象同样也有一个address()方法,用来获取TCP服务器绑定的地址,同样也是返回一个含有port、family、address属性的对象。通过socket对象可以获取客户端发送的流数据,每次接收到数据的时候触发data事件,通过监听这个事件就可以在回调函数中获取客户端发送的数据,代码如下: //引入net模块 const net = require('net'); //创建TCP服务器 const server = net.createServer(function (socket) { //监听data事件 socket.on("data", function (data) { //打印数据 console.log("接收到数据:" + data.toString()); }); }); //设置监听端口 server.listen(8001, function () { console.log("服务正在监听中。。。") }); 测试结果如下:  socket对象除了有data事件外,还有connect、end、error、timeout等事件。 1.6、发送数据给客户端 调用socket.write()可以使TCP服务器发送数据,这个方法只有一个必需参数,就是需要发送的数据;第二个参数为编码格式,可选。同时,可以为这个方法设置一个回调函数。当有用户连接TCP服务器的时候,将发送数据给客户端,代码如下: //引入net模块 const net = require('net'); //创建TCP服务器 const server = net.createServer(function (socket) { //设置消息内容 const message = "Hello Client......"; //发送数据 socket.write(message, function () { const writeSize = socket.bytesWritten; console.log("数据发送成功,数据长度为:" + writeSize); }); //监听data事件 socket.on("data", function (data) { const readSize = socket.bytesRead; //打印数据 console.log("接收到数据为:" + data.toString(), ";接收的数据长度为:" + readSize); }); }); //设置监听端口 server.listen(8001, function () { console.log("服务正在监听中。。。") }); 测试结果如下:  在上面这段代码中还用到了socket对象的bytesWritten和bytesRead属性,这两个属性分别代表着发送数据的字节数和接收数据的字节数。除了上面这两个属性外,socket对象还有以下属性: socket.localPort:本地端口的地址; socket.localAddress:本地IP地址; socket.remotePort:进程端口地址; socket.remoteFamily:进程IP协议族; socket.remoteAddress:进程IP地址。 # 2、构建TCP客户端 Node.js在创建一个TCP客户端的时候同样使用的是net(网络)模块。 ## 2.1、使用Node.js创建TCP客户端 为了使用Node.js创建TCP客户端,首先要调用require(‘net’)来加载net模块。创建一个TCP客户端只需要创建一个连接TCP客户端的socket对象即可: //引入net模块 const net = require('net'); //创建TCP客户端 const client = new net.Socket(); 创建一个socket对象的时候可以传入一个json对象。这个对象有以下属性: fd:指定一个存在的文件描述符,默认值为null; readable:是否允许在这个socket上读,默认值为false; writeable:是否允许在这个socket上写,默认值为false; allowHalfOpen:该属性为false时,TCP服务器接收到客户端发送的一个FIN包后,将会回发一个FIN包;该属性为true时,TCP服务器接收到客户端发送的一个FIN包后不会回发FIN包。 ## 2.2、连接TCP服务器 创建了一个socket对象后,调用socket对象的connect()方法就可以连接一个TCP服务器,代码如下: //引入net模块 const net = require('net'); //创建TCP客户端 const client = new net.Socket(); //设置连接的服务器 client.connect(8001, '127.0.0.1', function () { console.log("连接服务器成功"); }); 连接成功如下图所示:  ## 2.3、获取从TCP服务器发送的数据 socket对象有data、error、close、end等事件,因可以通过监听data事件来获取从TCP服务器发送的数据,代码如下: //引入net模块 const net = require('net'); //创建TCP客户端 const client = new net.Socket(); //设置连接的服务器 client.connect(8001, '127.0.0.1', function () { console.log("连接服务器成功"); }); //监听data事件 client.on("data", function (data) { //打印数据 console.log("接收到数据为:" + data.toString()); }); 先启动TCP服务端,再运行上面客户端,可以发现命令行中已经输出了来自服务端的数据,说明此时已经实现了服务端和客户端之间的通信:  ## 2.4、向TCP服务器发送数据 因为TCP客户端是一个socket对象,所以可以使用以下代码来向TCP服务器发送数据: //引入net模块 const net = require('net'); //创建TCP客户端 const client = new net.Socket(); //设置连接的服务器 client.connect(8001, '127.0.0.1', function () { console.log("连接服务器成功"); //给服务端发送数据 client.write("Hello Server......"); }); //监听data事件 client.on("data", function (data) { //打印数据 console.log("接收到数据为:" + data.toString()); }); //监听end事件 client.on("end", function () { console.log("客户端发送数据结束") }); 客户端控制台输出:  服务端控制台输出:  至此使用Node.js进行TCP网络通信完成,如有不对的地方欢迎指正
-
>摘要:包与NPM Node组织了自身的核心模块,也使得第三方文件模块可以有序的编写和使用。本文分享自华为云社区[《NodeJs深入浅出之旅:包与NPM》](https://bbs.huaweicloud.com/blogs/307034?utm_source=zhihu&utm_medium=bbs-ex&utm_campaign=other&utm_content=content),作者:空城机。 # 包与NPM Node组织了自身的核心模块,也使得第三方文件模块可以有序的编写和使用。 但是在第三方模块中,模块与模块之间仍然是散列在各地的,**相互之间不能直接引用** 所以在模块外,包和NPM是将模块联系起来的机制。 - 包组织模块示意图  CommonJS 的包规范定义其实也很简单,由包结构和包描述文件两部分组成。 # 包结构 用于组织包中的各种文件,是一个存档文件,即一个目录直接打包为.zip或tar.gz格式的文件。 符合规范的包目录: - package.json: 包描述文件 - bin: 用于存放可执行二进制文件的目录 - lib: 用于存放JavaScript代码的目录 - doc: 用于存放文档的目录 - test: 用于存放单元测试用例的代码 # package.json包描述文件 NPM所有行为都与包描述文件的字段息息相关 一些字段: - name: 包名。 规范定义需要用小写的字母和数字组成,不允许出现空格。 包名必须是唯一的,以免对外公布时产生重名冲突 - description: 包简介 - version: 版本号,关于其介绍在《Node.js学习(一)——简介》也有提及 - keywords: 关键字数组, NPM中主要用来作分类搜索。 - maintainers: 包维护者列表。 每个维护者由name、email和web这3个属性组成。 NPM通过这个属性进行权限认证。 格式: ```"maintainers":[{ "name":"kongchengji", "email":"111@.com", "web":"[http:](https://blog.csdn.net/qq_36171287)" }]``` - contributors: 贡献者列表,格式与维护者列表相同 - bugs: 一个可以反馈bug的网页地址或邮件地址 - licenses: 当前包所使用的许可证列表,表示包在哪些许可证下使用 格式: "licenses":[{ "type": "GPLv2", "url":"" }] // 或者 "license": "ISC" - repositories: 托管源代码的位置列表,表明可以通过哪些方式和地址访问包源代码。 - 格式: - "repository": { - "type": "git", - "url": "git+https://github.com/kongchengji/UiSelfMade.git" - }, - dependencies: 使用当前包所需要依赖的包列表。 这个属性非常重要 - homepage: 当前包的网站地址 - os: 操作系统支持列表, 如果列表为空,则不对操作系统做任何假设 - cpi: CPU架构支持列表 - engine:支持的JavaScript引擎列表 - directories:包目录说明 - implements: 实施规范的列表。 标志当前包实现了CommonJS哪些规范 - scripts: 脚本说明对象。 主要用于被包管理器用来安装、编译、测试和卸载包 "scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "lint": "eslint --ext .js,.vue src", "build": "node build/build.js" }, NPM与包规范区别在于多了四个字段: - author: 包作者 :ok_man: - bin: 一些包作者希望包可以作为命令行工具使用。 - main: 模块引入包时,会有限检查这个字段,并将其作为包中其余模块的入口模块。 如果不存在,require会查找包目录下的index.js、index.node、index.json作为默认入口 - devDependencies: 一些模块只在开发时需要依赖。 devDependencies:开发环境使用 dependencies:生产环境使用 # 前后端共用模块 JavaScript在Node出现后,有一项优势 --> 一些模块可以在前后端实现共用。 但是前后端上始终还是有一些差别的 :sweat_drops: # 前后端模块侧重点 前后端JavaScript分别搁置在HTPP的两端,扮演的角色并不同。 浏览器端的JavaScript需要经历从同一个服务器端分发到多个客户端执行,瓶颈是带宽,从网络加载代码 服务器端的JavaScript是相同代码需要多次执行,瓶颈是CPU和内存等资源,从磁盘中加载 在前端JavaScript中,主要还是应用**AMD规范**。 CommonJS并不完全适用于前端JavaScript,比如Node的模块引入基本是同步的,但是前端引入如果使用同步引入,UI在初始化过程中需要花费很多时间等待脚本加载完成。 # AMD规范 AMD规范 是CommonJS规范的一个延伸,全称:Asynchronous Module Definition。 是异步模块定义 模块定义:define(id?, dependencies?, factory); id 是模块的名字,它是可选的参数。 dependencies 指定了所要依赖的模块列表,它是一个数组,也是可选的参数 AMD需要在声明模块时指定所有的依赖,通过形参传递依赖到模块内容中: define(['./a', './b'], function (dep1, dep2) { a.doSomethimg() b.doSomething() }); # CMD规范 与AMD规范相对的还有CMD规范,全称:Common Module Definition。 是公共模块定义 这是由国内的玉伯(也是一位大佬)提出的 模块定义:define(factory) CMD支持动态引入: define(function(require, exports, module) { var a=require('./a') a.doSomethimg() var b=require('./b') b.doSomething() }) 在需要依赖模块时, 随时调用require()引入即可 CMD 推崇依赖就近; AMD 推崇依赖前置 CMD 是延迟执行; AMD 是提前执行 CMD性能好,因为只有用户需要的时候才执行; AMD用户体验好,因为没有延迟,依赖模块提前执行了 AMD和CMD最大的区别是对依赖模块的执行时机处理不同 # 兼容多种模块规范 创建一个hello方法,让hello方法能在不同运行环境中运行,兼容Node、AMD、CMD和常见浏览器 匿名函数前加一个;是个好习惯 name是方法名,definition是方法体 通过typeof检测环境是否为AMD或CMD还是Node环境 可以将模块执行结果挂载在window变量中,这样可以直接调用 // 匿名函数前加一个;是个好习惯 name是方法名,definition是方法体 ;(function (name, definition) { //检查环境是否是AMD或CMD var hasDefine = typeof define === 'function', // 检查环境是否为Node hasExports = typeof module !== 'undefined' && mudule.exports; if(hasDefine) { define(definition); } else if (hasExports) { module.exports = definition(); } else { // 将模块的执行结果挂在window变量中,在浏览器中this指向window对象 this[name] = definition(); } })('hello', function () { var hello = function () { console.log('hello'); } return hello; });
上滑加载中
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签