分类目录归档:佳佳教程

解决Macbook休眠异常 待机掉电过快

请先确认apple官方给出的方法都没有用之后再尝试此文方法!

曾经我的mbp拔掉电源合上盖子以后一天过去几乎都不怎么掉电,基本上会少个百分之一到三。但是最近一年不知道怎么回事,待机一天过去电量会掉一半多(并不是因为电池老化)。我也不清楚是从什么时候开始这样的了,也许是某次系统升级后吧,毕竟我也没有特别去动过电源设置。

原本我也一直想找到导致这个问题最根本的原因,不过试了很多次都没找到。最近买了mbp的sea也有同样的问题,于是想着干脆把这个问题强行解决掉算了。

继续阅读解决Macbook休眠异常 待机掉电过快

Rust 基本数据类型

之前就有点感兴趣,现在又仔细看了以下,并做个笔记。(并不是表示我要学会,只是稍作了解。这种编译型静态类型语言我还是更倾向用c++)

下面变量全都加了下划线前缀是因为变量定义了不使用的话编译器会给出警告,除非加了_前缀。

fn main(){
    //整数
    let _a=1; 
    let _e:u8=128;//unsigned 8bit int (类型定义在变量名后)
    //以下几个是类型跟在数据后
    let _c=128u8;//unsigned int 8bit
    let _f=123i16;//signed int 16bit
    let _g=123i32;//signed int 32bit
    let _h=123i64;//signed int 64bit
    let _i=123isize;//signed int,位数与cpu通用寄存器位宽相关
    let _j=123usize;//unsigned int ,同上

    //分隔符_,不影响内容
    let _d1=98_22_2;//98222

    //其它进制表示
    let _h1=0xff;//16进制
    let _o1=0o77;//8进制
    let _b1=0b11111111;//2进制
    let _byte1=b'A';//用char表示的unsigned int 8

    //32和64位浮点数,同样为两种类型定义方式
    let _f1:f32=2.0;
    let _f2:f64=2.0;
    let _f3=2.0f32;
    let _f4=2.0f64;

    //bool
    let _boo1=false;
    let _boo2:bool=false;

    //字符
    let _s1='a';
    let _s1_1:char='a';
    let _s2:char='🐱';//rust中的char不是单纯的ascii字符,而是Unicode标量
    let _s3="abcd";//静态字符串


    //元组
    let _tup:(i32, f64, u8) = (500, 6.4, 1);
    let _tup2 = (500:i32, 6.4:f64, 1:u8);//实验性写法,可能会取消或加入规范,不建议使用
    let _tup3=(1,2,3);//自动判断类型

    let (_x, _y, _z) = _tup;//元祖解构,获得_x,_y,_z三个变量
    let (_x2, _y2, _z2) = (1i32,1i64,1isize);//吃饱了撑的写法,和定义三个变量并赋值等效

    let _tup0=_tup.0;//获取元祖的第0个元素

    //数组
    let _arr = [1, 2, 3, 4, 5];
    let _arr2=["a","b","c"];
    let _arr3: [i32; 5] = [1, 2, 3, 4, 5];//声明数组的数据类型以及数据数量
    let _arri0=_arr[0];//获取数组第0个元素

}

 

npm多用户

npm的用户登录信息写在用户目录的`.npmrc` 文件里,所以同一时间只能登录一个账号,要切换账号的话就要重新用`npm login` 登录,比较麻烦。

于是写了个切换.npmrc文件来直接切换用户的shell脚本

分别login到对应的用户,然后查看用户目录里的.npmrc文件内容,复制出来,填到下面对应的地方

#!/bin/bash
if [ $1 = "user1" ]
then
	echo "user : $1";
	echo -e "registry=http://registry.npmjs.org/\n//registry.npmjs.org/:_authToken=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" > ~/.npmrc;
elif [ $1 = "user2" ]
then
	echo "user : $1";
	echo -e "registry=http://registry.npmjs.org/\n//registry.npmjs.org/:_authToken=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" > ~/.npmrc;
fi

保存成比如`npmuser` 文件放在某个PATH目录里,然后用`npmuser user1` 这样的命令就可以直接切换用户而不用再登录了。

[Javascript]判断是否为触摸操作模式

写了段代码可以用来识别用户的操作方式是否为触摸。

首先需要给元素加一个便于批量添加事件的on方法(我自认为这么写没什么毛病

(function(){
	function Extent_On_Event(){
		if(arguments[0] instanceof Array){
			var arg=arguments,es=arguments[0];
			es.forEach(function(e){
				arg[0]=e;
				this.addEventListener.apply(this,arg);
			});
		}else{
			this.addEventListener.apply(this,arguments);
		}
		return this;
	};
	(window.EventTarget||window.Node).prototype.on=Extent_On_Event;
	if(!window.on)Window.prototype.on=Extent_On_Event;
})();

然后定义判断触摸模式的代码

//touchMode
(function(){
	var isTouchMode=window.touchMode=('ontouchstart' in window);
	var mouseEventRec=0;
	function touchModeEvent(node){
		node.on(['touchstart','touchend','touchmove'],function(){
			mouseEventRec&&(mouseEventRec=0);
			if(isTouchMode)return;
			isTouchMode=window.touchMode=true;
			var e=new Event('touchModeChange');
			e.touchMode=isTouchMode;
			window.dispatchEvent(e);
		});
		node.on('mousemove',function(){
			if(!isTouchMode)return;
			mouseEventRec++;
			if(mouseEventRec>4){
				isTouchMode=window.touchMode=false;
				var e=new Event('touchModeChange');
				e.touchMode=isTouchMode;
				window.dispatchEvent(e);
			};
		});
	}
	touchModeEvent(window);
})();

这段代码的作用

  • 在`window` 对象上定义touchMode变量,值为boolean,为true时是触摸模式,为false时是非触摸模式(大概就是鼠标模式)。如果你不希望出现此变量,删除相关赋值代码即可。
  • 模式变动时在`window` 对象上触发`touchModeChange` 事件,event对象的touchMode属性为变动后的值。

在支持触摸的设备上,touchMode默认为true,移动鼠标后会转变为false。我认为这个地方是有点毛病的,但是不知道如何正确判断初始状态。

对于阻止以上代码中事件冒泡到window的元素,需要额外执行相关的监听代码以保证正确性。

[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: 加入出错时不退出的方法

让Windows在高DPI显示屏上正确显示

我在macbook上虚拟机里装了个Win10,装好了之后发现,一切都是那么的小,小的几乎看不清。因为这个macbook是Retina屏的,所以dpi比较高,于是东西都变小了。

我的标题里不直接写win10是因为我也不知道自定义项目大小是从哪个系统开始有的,没有这个功能的系统很简单,就是把分辨率按比例调低即可。

继续阅读让Windows在高DPI显示屏上正确显示

[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]批量重命名音乐专辑内音乐文件名

[Javascript]使用Generator函数创建你自己的异步函数

欢迎来到佳佳doubi小课堂~在这里你可以学到实用又错误的知识×。

好久没写正经的博文了,让我来正经一下。

使用Generator函数来创建你的异步函数,先说明一下原理。

Generator函数是ES6里的新函数类型,函数定义写作这样

function* a(){
	…
}

看到没,在函数名和function之间多了一个*号,这不是我写错了,是Generator函数的标志,这个*号其实也可以贴着函数名写`function *a(){}`,也可以不加空格`function*a(){}`,不过还是推荐把它贴着function写,这样既不会影响一些编辑器里的高亮,也不会降低代码可读性。 继续阅读[Javascript]使用Generator函数创建你自己的异步函数

[Node.js]isFile

昨天被nodejs的`isfile` 坑了一下午。

本来我是这么用的

var fs=require("fs");
var stat=new fs.Stats();

stat.isFile(文件路径);

结果没有任何返回,也没有报错。于是我就研究了一下午是不是相对路径问题,是不是系统问题什么的。。。

为什么我要这么写呢,因为API文档很简单就带过了这个内容,连个例子也没有:


 

Class: fs.Stats

`fs.stat()` , `fs.lstat()`  和 `fs.fstat()`  以及他们对应的同步版本返回的对象。

stats.isFile()
stats.isDirectory()
stats.isBlockDevice()
stats.isCharacterDevice()
stats.isSymbolicLink() (仅在与 fs.lstat()一起使用时合法)
stats.isFIFO()
stats.isSocket()

 


由于看到了`class fs.Stats` ,我第一反应就是先`new` 一个出来,结果就悲剧了。后来经过不断探索,昂头奋进,披荆斩棘,终于从废渣信息爆满的百度里找到了`isFile` 的正确用法,是这样:

var fs=require("fs");
fs.statSync(路径).isFile();//同步版

fs.stat(path,function(s){//异步版
	callback(s.isFile());
});

`isDirectory()` 和`isFile()` 同理

[PHP]禁止json_encode显式转换为UTF8编码

我今天发现弹幕播放器载入的弹幕虽然不多,但是传回的弹幕json却很大,于是我想起了一个鬼故事[json_encode对[非正常字符]的显式utf8转换],所以很多弹幕数据会被转换成字符形式的utf8码『\uxxxx』,虽然英文字符和中文字符实际上占用的大小不一样,不过把文字显式转换成utf8码仍然是额外消耗空间的,json完全可以保留原本的文字进行json格式化。

那么现在问题来了,会画画的妹纸好还是会唱歌的妹纸好呢
那么现在问题来了,json是否可以直接取消utf8转换呢?如果可以那真是极好,要是不可以的话还得在转换以后正则替换掉所有utf8码。

还好json_encode的第二个设置参数可以设置

 json_encode(数组,JSON_UNESCAPED_UNICODE);

这样就可以取消utf8显式转换了,某视频的弹幕返回的json也从90+K变成了50+K。