当前位置: 首页 > 后端技术 > Node.js

Node.jsutil模块解读

时间:2023-04-03 12:37:34 Node.js

util模块的初衷是为内部API提供一些工具支持。但是很多实用函数对于普通开发者来说也是非常有用的,所以util模块对外暴露了一些方法。本文主要讨论以下三个方面的工具功能:样式转换,调试输出,过时的API,样式转换,回调转换,promise,对于传入错误优先回调作为函数最后一个参数的函数(如fs.readFile('./filename',(err,data)=>{})),util提供了promisify(original)方法将此类函数转换为返回promise的形式。以fs.readFile为例constfs=require('fs');fs.readFile('./h.js',(err,data)=>{if(err){console.error(err);return;}console.log(data.toString());})//Constfs=require('fs');constutil=require('util');constreadFilePromise=util.promisify(fs.readFile);readFilePromise('./h.js').then((data)=>{console.log(data.toString());},(err)=>{console.error(err);});promisify执行后,返回一个新的函数。新函数的执行结果是一个promise。新函数会调用原来的原始方法,并自动添加一个错误优先类型的回调。根据原文判断执行结果是resolve还是reject,简单版代码如下:functionpromisify(original){functionfn(...args){constpromise=createPromise();try{original.call(this,...args,(err,...values)=>{if(err){promiseReject(promise,err);}else{promiseResolve(promise,values[0]);}});}catch(err){promiseReject(promise,err);}返回承诺;}returnfn}util模块也提供了promisesify的自定义转换方法(util.promisify.custom属性定义在原函数上),例如下面的方法可以用来禁止文件读取。util.promisify.custom必须在调用util.promisifyconstfs=require('fs');constutil=require('util');fs.readFile[util.promisify.custom]=(fileName)=>{returnPromise.reject('不允许');}constreadFilePromise=util.promisify(fs.readFile);readFilePromise('./h.js').then((data)=>{console.log(data.toString());},(err)=>{console.error(err);//不允许});从promise到callbackutil的callbackify方法正好和promisify相反。callbackify用于将异步(或返回承诺)函数转换为遵循错误优先回调样式的类型。constutil=require('util');constfn=()=>{return'fnexecuted'};functiondelay(second,fn){returnnewPromise((resolve,reject)=>{setTimeout(()=>{resolve(fn());},second);});}delay(1000,fn).then((data)=>{console.log(data);//fnexecuted});//ConstdelayFn=util.回调(延迟);delayFn(1000,fn,(错误,数据)=>{如果(错误){console.error(错误);返回;}console.log(数据);//fn执行});有一个情况需要注意,如果promise是reject(null||0||false),那么callback如果err判断为false,程序会继续执行console.log(data),其实是不正确的所以callbackify针对这种情况做了特殊的处理(创建错误,将原始信息放在错误的reason属性上,并将错误传递给最终的回调函数)functioncallbackifyOnRejected(reason,cb){if(!reason){constnewReason=newERR_FALSY_VALUE_REJECTION();newReason.reason=原因;原因=新原因;Error.captureStackTrace(原因,callbackifyOnRejected);}returncb(reason);}具体实现逻辑是通过then回调方法调用原函数originalfunctioncallbackify(original){functioncallbackfied(...args){constmaybeCb=args.pop();constcb=(...args)=>{Reflect.apply(maybeCb,this,args);};Reflect.apply(original,this,args).then((ret)=>process.nextTick(cb,null,ret),(rej)=>process.nextTick(callbackifyOnRejected,rej,cb));}returncallbackfied;}调试输出util.debuglog(section)debuglog方法用于根据NODE_DEBUG环境变量有选择地输出调试信息,比如下面这个例子//index.jsconstutil=require('util');常量调试日志=实用程序。debuglog('foo-bar');debuglog('hellofromfoo[%d]',123);//执行索引文件nodeindex.js//无输出NODE_DEBUG=foo-barnodeindex.js//FOO-BAR18470:你好,是foo-bar[2333]NODE_DEBUG如果要输出多个section,可以用逗号分隔,NODE_DEBUG也支持通配符(nodeversionRequires10)NODE_DEBUG=fs,net,tls//多段NODE_DEBUG=foo*//通配符上面的debuglog函数在执行时支持占位符。其实底层使用的是util.format方法util.formatutil.format用于占位符替换。不同类型的数据用不同的占位符表示%s字符串%d整数或浮点数%i整数%f浮点数%jJSON%oObject(包括不可枚举属性)%OObject(不包括不可枚举属性)%%output%util.inspect方法其实是在格式化Object的输出字符串时使用的,%o和%O的区别在于调用inspect方法时传入的配置项不同%o传给util的配置项.inspectare{showHidden:true,showProxy:true}util.inspectutil.inspect用于对对象进行格式化字符串操作,提供个性化的配置项constutil=require('util');varchild={"name":"child","age":18,"friends":[{"name":"randal","age":19,"friends":[{"name":"Kate","age":18}]}],"motto":"现在这不是结束。它甚至不是结束的开始。但它也许是开始的结束。"}console.log(util.inspect(child,{紧凑:假,深度:空,breakLength:80}));compact用于在一行上显示每个属性。depth用于控制显示层级,默认为2breakLength为一行最大文本数,如果超过换行,更详细的参数和定义请参考官网api=()=>{console.log('oldfn');};classoldClass{constructor(){console.log('老班级');}}constfn1=util.deprecate(oldFn,'deprecatedfn');constfn2=util.deprecate(oldClass,'deprecatedclass');fn1();newfn2();//输出旧的fnoldclass(node:18001)DeprecationWarning:deprecatedfn(node:18001)DeprecationWarning:deprecatedclassimplementfunctiondeprecate(fn,msg,code){letwarning=false;functiondeprecated(...args){if(!warned){warned=true;if(code!==undefined){if(!codesWarned[code]){process.emitWarning(msg,'DeprecationWarning',code,deprecated);//发出警告信息codesWarned[code]=true;//避免重复提示相同的errorCode}}else{process.emitWarning(msg,'DeprecationWarning',deprecated);}}if(new.target){//类类型returnReflect.construct(fn,args,new.target);}返回fn.apply(this,args);//functiontype}returndeprecated;}相关命令行配置项命令行选项process属性不输出警告信息--no-deprecation--no-warningsnoDeprecation输出详细的堆栈信息--trace-deprecation--trace-warningstraceDeprecation抛出错误异常--throw-deperecationthrowDeprecation其他除了上面提到的三个工具,util.types还提供了非常丰富的类型识别方法(isGeneratorFunction,isWeakSet,isPromise,isArrayBuffer)等。以后需要进行类型判断时,可以考虑使用util模板https://nodejs.org/dist/latest-v10.x/docs/api/util提供的这些方法参考。网页格式