标签归档:node.js

[Node.js]ES模块和CommonJS模块的导入

在使用ES导入语法的文件中想要使用require导入一个CommonJS模块的话,可以使用module.createRequire来创建一个require函数。

import { createRequire } from 'module';
const require = createRequire(import.meta.url);

 

在一般的使用CommonJS导入语法的文件中想要使用ES语法导入模块的话,可以使用import函数,要注意的是这是一个异步函数,返回一个Promise,所以需要await它或者使用then来等待返回结果,如下

(async()=>{
	const fs=await import('fs);
})();

 

[Browserify]异步插件导致write after end错误

写了个Browserify插件,之前一直没问题,但今天我改了点打包流程,结果一直报write after end错误,找了半个晚上,发现是因为我的插件函数写的是异步的,里面有个await异步读文件。

之前一直没出问题是因为后面的打包流程时间够长,能让这个插件正常执行完,但今天改了流程之后部分情况下很快就执行完了,于是当插件异步流程执行完后继续就出错了,修正方法是把异步文件读取改成同步的。

[Node.js]进程异常退出,错误码 3221226505

不是我想水一篇博文,在解决完前一篇博文的问题之后,立刻就又碰上另一个奇葩问题,进程直接跑着跑着没了,留下一个错误码3221226505。

在我左思右想把代码改来改去,包换来换去之后依然不能解决问题,然后发现是canvas包的问题,之所以一直没有发现是它,是因为出问题的代码里并没有用到这个包,它是在别的地方被引用到的,可能它的二进制模块破坏了node的环境,导致别的代码执行的时候触发了异常导致程序崩溃。

这个问题其实也不是第一次出现了,而且每次都是因为项目中同时有canvas和sharp两个模块才出现问题,在某些版本下不会出问题,某些版本下又会出现不一样的错误,这次就是和上次不一样所以才没能快速发现。

就这点破事,又浪费了我一个晚上,这时候我真想给搞出这bug的人屁股上来一脚。

[Node.js]解决‘gbk’ codec can’t decode byte 0x80 in position

每次换一个环境执行npm i都会碰到这样的问题,记录一下解决方法,

方法1:手动去报错的文件里指定编码为UTF-8,我自己第一次解决这个问题就是用的这个办法,刚刚想找找看有没有别的解决方法的时候发现别人也有去手动改源码的,放个参考链接

简单地说就是找到报错的那行,给open函数加个encoding='utf-8' 参数就可以解决问题,但这样属于改了人家文件,更新后还是会变回去的,所以现在我不这样做了。

方法2:去控制面板的区域设置里到“管理”标签页下,“更改系统区域设置”,把“Beta版:使用Unicode UTF-8提供全球语言支持(U)”勾上,然后重启一下,python就会默认用utf-8来读文件了。

这个方法会改变整个系统的默认代码页,最主要的影响是会导致使用非Unicode的程序乱码甚至崩溃,还有在gbk设置时以ansi保存的含有中文的bat脚本会乱码。如果影响不大的话倒是可以让系统一直保持在这个区域选项上,影响某些软件的正常使用的话在执行完需要的编译任务后还得改回去。在这种模式下可以使用“locale emulator”这样的软件以Chinese模式启动程序,以解决程序的乱码和崩溃问题。

方法3:我没试过,理论上应该可行,从python本体入手,把它的默认编码设置成utf-8,参考这里的方案2。这个没用

[Node.js]file-namer 文件重命名工具

昨晚写了个重命名工具,使用正则表达式匹配并替换文件名。

现在给npm包起个合适的名字是真难

GitHub: https://github.com/JiaJiaJiang/node-namer

效果

$ namer -f "/.+(?=\.txt$)/" -r "#COUNTERpoi$&"
match: /.+(?=\.txt$)/   find: /.+(?=\.txt$)/   replacement: #COUNTERpoi$&
Match list:
1.txt   >       1poi1.txt
2.txt   >       2poi2.txt
3.txt   >       3poi3.txt
4.txt   >       4poi4.txt
5.txt   >       5poi5.txt
6.txt   >       6poi6.txt
7.txt   >       7poi7.txt
8.txt   >       8poi8.txt
9.txt   >       9poi9.txt
10.txt  >       10poi10.txt
11.txt  >       11poi11.txt
12.txt  >       12poi12.txt
13.txt  >       13poi13.txt
14.txt  >       14poi14.txt
15.txt  >       15poi15.txt
16.txt  >       16poi16.txt
17.txt  >       17poi17.txt
18.txt  >       18poi18.txt
19.txt  >       19poi19.txt
20.txt  >       20poi20.txt
21.txt  >       21poi21.txt
22.txt  >       22poi22.txt
23.txt  >       23poi23.txt
24.txt  >       24poi24.txt
25.txt  >       25poi25.txt
26.txt  >       26poi26.txt
27.txt  >       27poi27.txt
28.txt  >       28poi28.txt
29.txt  >       29poi29.txt
30.txt  >       30poi30.txt
31.txt  >       31poi31.txt
32.txt  >       32poi32.txt
33.txt  >       33poi33.txt
34.txt  >       34poi34.txt
35.txt  >       35poi35.txt
36.txt  >       36poi36.txt


36matches found.
Confirm?    (control+c to exit)

Finished. 36succeeded,0failed

 

[Node.js]拦截process.stdout和process.stderr

由于解决这个问题花了我一些时间,所以记录一下说不定可以帮到其他人。

process.stdout是一个getter,所以我们不能用普通的替换来换掉process.stdout来拦截写入它的数据。同时,process.stdout是一个Writable Stream,所以也不能简单地直接从它里面获取写入的数据。

 

一开始我花了不少时间来研究怎么可以从这个Writable Stream里读出数据,但是这似乎太麻烦了,然后我甚至想到了利用child process来拦截数据。最后发现其实很简单,我们只要重新定义这个Getter就可以了。

var stream=require('stream');


var rawStdout=process.stdout,//先拿到原来的stdout
	newStdout=new stream.PassThrough();//创建一个passthrough流,这是一种特殊的Transform流,会直接把写入的数据吐出来
process.__defineGetter__('stdout',function(){//重新定义process.stdout的Getter
	return newStdout;//返回我们的passthrough流
});

这样我们就成功拦截到标准输出了,要注意,这段代码必须放在有任何输出之前,一旦在之前有了内容输出,它就没用了。

然后我们就可以自己决定怎么处理stdout了比如:

newStdout.pipe(rawStdout);//内容输出到控制台

newStdout.pipe(文件的writable stream);//内容写入文件

newStdout.pipe(其它可写流);//随你怎么处理

 

 

同理,process.stderr也可以这样拦截

[Node.js]防止node自动退出

node执行完所有代码以后就会退出(部分监听服务除外),如果不希望node立刻退出,只要在任意位置加上一行

setInterval(function(){},9999999);//时间设置多少都没有关系,这只影响这个空回调函数的调用频率

node就不会退出了(除非出错

如果你希望即使是出错了,也不让Node退出,那么就需要加入以下事件监听器

process.on('uncaughtException',(err,origin)=>{//捕捉uncaughtException
	console.error('[uncaughtException]',err,origin);
});

process.on('unhandledRejection',(err,promise)=>{//捕捉unhandledRejection
	console.error('[unhandledRejection]',err);
});

加入这两个监听器之后,node遇到任何未捕捉的错误,都会交给第一个监听器处理,碰到任何未catch的异常Promise,都会交给第二个监听器处理,你可以在里面做些事情,比如打个日志之类的。

==========更新log===========

  • 2021/11/16: 加入出错时不退出的方法

node被抛弃,iojs取而代之

从node分离出来农民起义的iojs终于取得了革命胜利。现在node的版本一下从0.12.x飞升到了4.0.0。

Node.js ChangeLog
2015-09-08, Version 4.0.0 (Stable), @rvagg

Notable changes

This list of changes is relative to the last io.js v3.x branch release, v3.3.0. Please see the list of notable changes in the v3.x, v2.x and v1.x releases for a more complete list of changes from 0.12.x. Note, that some changes in the v3.x series as well as major breaking changes in this release constitute changes required for full convergence of the Node.js and io.js projects.

child_process: ChildProcess.prototype.send() and process.send() operate asynchronously across all platforms so an optional callback parameter has been introduced that will be invoked once the message has been sent, i.e. .send(message[, sendHandle][, callback]) (Ben Noordhuis) #2620.
node: Rename "io.js" code to "Node.js" (cjihrig) #2367.
node-gyp: This release bundles an updated version of node-gyp that works with all versions of Node.js and io.js including nightly and release candidate builds. From io.js v3 and Node.js v4 onward, it will only download a headers tarball when building addons rather than the entire source. (Rod Vagg) #2700
npm: Upgrade to version 2.14.2 from 2.13.3, includes a security update, see https://github.com/npm/npm/releases/tag/v2.14.2 for more details, (Kat Marchán) #2696.
timers: Improved timer performance from porting the 0.12 implementation, plus minor fixes (Jeremiah Senkpiel) #2540, (Julien Gilli) nodejs/node-v0.x-archive#8751 nodejs/node-v0.x-archive#8905
util: The util.is*() functions have been deprecated, beginning with deprecation warnings in the documentation for this release, users are encouraged to seek more robust alternatives in the npm registry, (Sakthipriyan Vairamani) #2447.
v8: Upgrade to version 4.5.103.30 from 4.4.63.30 (Ali Ijaz Sheikh) #2632.
Implement new TypedArray prototype methods: copyWithin(), every(), fill(), filter(), find(), findIndex(), forEach(), indexOf(), join(), lastIndexOf(), map(), reduce(), reduceRight(), reverse(), slice(), some(), sort(). See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray for further information.
Implement new TypedArray.from() and TypedArray.of() functions. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray for further information.
Implement arrow functions, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions for further information.
Full ChangeLog available at https://github.com/v8/v8-git-mirror/blob/4.5.103/ChangeLog

以上是搬过来的changeLog,同时在changeLog页面往下翻一番,全都是iojs之前的版本号,很明显node原本的项目是直接被iojs项目覆盖掉了,注意这一行
node: Rename "io.js" code to "Node.js" (cjihrig) #2367.

iojs重命名为nodejs,革命军变成了正规军,推翻了原本的帝国统治。

现在点开iojs.org官网里的changelog也是直接跳转到https://github.com/nodejs/node/blob/master/CHANGELOG.md,也就是node的changelog。

 

这对native mod开发者来说是个福音,不用再去考虑兼容iojs和node携带的两个版本差距悬殊的v8版本了。

Error: Cannot find module ‘npmlog’

手动安装node的时候一不注意就会出现这个错误,装好了之后使用命令npm 测试一下出来了这个错误:Error: Cannot find module 'npmlog' 。

 

这一般是放在/bin里的链接不对导致的。

可能情况1

链接指向的不是node_modules/npm/bin/npm-cli.js ,初次手动安装难免会搞不清要链接哪个文件,把链接指向正确的位置即可。

情况2

使用的不是软链接,由于npm-cli.js中使用的是相对路径,要是你一不小心链了个硬链接,那么npm就会从/bin解析相对路径,所以就找不到npmlog模块了。要使用软链接,在ln命令后加上-s 选项:ln -s node_modules/npm/bin/npm-cli.js /bin/npm

 

解决node无法调用全局模块的问题

刚刚我把SPDY装到全局,npm -g install spdy ,

spdy@2.0.4 /usr/local/lib/node_modules/spdy
├── http-deceiver@1.2.4
├── handle-thing@1.2.4
├── select-hose@2.0.0
├── debug@2.2.0 (ms@0.7.1)
└── spdy-transport@1.1.8 (obuf@1.1.1, wbuf@1.7.0, hpack.js@2.1.4, readable-stream@2.0.2)

可以看到这个模块被装到/usr/local/lib/node_modules里了

 

 

 

然后开个环境测试一下,结果

> require('spdy')
Error: Cannot find module 'spdy'
    at Function.Module._resolveFilename (module.js:336:15)
    at Function.Module._load (module.js:286:25)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at repl:1:1
    at REPLServer.defaultEval (repl.js:154:27)
    at bound (domain.js:254:14)
    at REPLServer.runBound [as eval] (domain.js:267:12)
    at REPLServer.<anonymous> (repl.js:308:12)
    at emitOne (events.js:77:13)

吓得我满脑子都是doge!!!这是为什么?

继续阅读解决node无法调用全局模块的问题

[Node.js]用ws模块创建加密的ws服务(wss)

node的ws模块可以很方便地创建一个单纯的标准websocket服务,但是对于创建wss服务并没有提供一个独立的方法,还是使用创建ws服务的方法,在传入参数对象里加了个自定义的https服务。

 

也不知道是我找错了文档还是官方文档就那么简洁,不过readme文件写的文档的确是这个→doc/ws.md,然后我研究了好几天还翻了遍它的源码和examples才终于理解了这个文档。

继续阅读[Node.js]用ws模块创建加密的ws服务(wss)

[Node.js]批量重命名音乐专辑内音乐文件名

这只是个便签博,方便以后再拿出来用。。

刚刚下了个LL大法的全套音乐专辑,(原谅我又盗版了),然后里面每个CD的音乐都是一如既往有编号的,不过我们放进自己播放列表的话并不需要这些编号,所以我要把它们去掉。

 

作为一个程序员,怎么能一个个手动改名呢,这简直是耻辱!

继续阅读[Node.js]批量重命名音乐专辑内音乐文件名