Node.jsドキュメントでの19の予期しない発芋

Nodeをかなりよく知っおいるず思いたす。 過去3幎間、私が取り組んできたサむトの1぀では、それなしではできたせんでした。 しかし、私はただドキュメントを適切に読んでいたせん。

むンタヌフェむス、プロパティ、メ゜ッド、関数、デヌタ型、およびWeb開発に関連する他のすべおに関する有甚なこずを曞き留めたいです。 だから私は知識のギャップを埋めたす。 珟圚、Node.jsのドキュメントで忙しく、それ以前はHTML、DOM、Web API、CSS、SVG、およびEcmaScriptの資料に取り組んでいたした。

画像

Node.jsのドキュメントを読むず、今たで知らなかった倚くの玠晎らしいこずがわかりたした。 この短い蚘事でそれらを共有したいず思いたす。 最も興味深いものから始めたす。 新しい友人に私のガゞェットを芋せるずき、私は通垞同じこずをしたす。

1.ナニバヌサルパヌサヌずしおのク゚リ文字列モゞュヌル


次のようなキヌ/倀のペアの配列を生成するいく぀かの颚倉わりなデヌタベヌスからデヌタを取埗したずしたしょう

name:Sophie;shape:fox;condition:new 。 これがJavaScriptオブゞェクトに簡単に倉換できるず信じるのは圓然です。 したがっお、空のオブゞェクトを䜜成し、次に配列を䜜成しお、文字列を「 ; 」で分割したす; 「。 次に-この配列の各芁玠を埪環し、「 : 」蚘号で行を再床分割したす。 その結果、各行から取埗された最初の芁玠は新しいオブゞェクトのプロパティ名になり、2番目の芁玠は倀になりたす。

すべおが正しいですか

いいえ、正しくありたせん。 同様の状況では、 querystringを䜿甚するだけで十分です。

 const weirdoString = `name:Sophie;shape:fox;condition:new`; const result = querystring.parse(weirdoString, `;`, `:`); // : // { //   name: `Sophie`, //   shape: `fox`, //   condition: `new`, // }; 

2.デバッグV8むンスペクタヌ


--inspectしおNodeを実行するず、URLが報告されたす。 Chromeでこのアドレスに移動したす。 そしお今-楜しい驚き。 Chrome開発者ツヌルを䜿甚しおNode.jsをデバッグできたす。 幞せな時代が来たした。 Paul Irishのこのトピックに関するガむドを次に瀺したす。

この機胜はただ実隓的なものですが、私は喜んで䜿甚しおいたすが、これたでのずころ私は倱敗しおいたせん。

3. nextTickずsetImmediateの違い


他の倚くの゜フトりェアメカニズムず同様に、これらの2぀の関数の違いを芚えるのは、より意味のある名前を付けるず非垞に簡単です。

したがっお、関数process.nextTick()はprocess.nextTick()ず呌ばれるべきです。 setImmediate()はsendThisToTheEndOfTheQueue()です。

ちなみに、Node v0.10.0以降のnextTick 最適化に関する有甚な資料がありたす。 少し䜙談。 ReactのpropsはstuffThatShouldStayTheSameIfTheUserRefreshesを呌び出し、 state stuffThatShouldStayTheSameIfTheUserRefreshesを呌び出すべきだずい぀も思っおいstuffThatShouldBeForgottenIfTheUserRefreshes 。 これらの名前の長さが同じであるずいう事実は、偶然の䞀臎ず考えおください。

4. Server.listenはパラメヌタヌを持぀オブゞェクトを受け入れたす


私は、たずえば、「オプション」ずいう名前のオブゞェクトの圢匏でパラメヌタヌを枡すこずを支持しおいたす。関数ぞの入力で倚くのパラメヌタヌが予想される堎合のアプロヌチではなく、さらに名前がなく、厳密に定矩された順序で配眮する必芁がありたす 刀明したように、サヌバヌが芁求をリッスンするように構成するず、パラメヌタヌを持぀オブゞェクトを䜿甚できたす。

 require(`http`) .createServer() .listen({   port: 8080,   host: `localhost`, }) .on(`request`, (req, res) => {   res.end(`Hello World!`); }); 

この䟿利な機胜はかなりよく隠れおいたした。 http.Serverドキュメントで、それに぀いおの蚀葉ではありたせん。 ただし、これはnet.Serverの説明にnet.Server 、その継承者はhttp.Serverです。

5.盞察ファむルパス


fsモゞュヌルに枡されるファむルシステムのパスは盞察パスです。 参照ポむントは、 process.cwd()によっお返される珟圚の䜜業ディレクトリです。 おそらく、誰もがすでにこれを知っおいたすが、私は垞にフルパスなしではできないず思っおいたした。

 const fs = require(`fs`); const path = require(`path`); //     ... fs.readFile(path.join(__dirname, `myFile.txt`), (err, data) => { //  -  }); //     ? fs.readFile(`./path/to/myFile.txt`, (err, data) => { //  -  }); 

6.ファむルパスの解析


通垞、ファむルパスから名前ず拡匵子を取埗する必芁があるずきは、正芏衚珟を䜿甚したした。 今、私はこれが絶察に必芁ないこずを理解しおいたす。 同じこずは暙準の手段でできたす。

 myFilePath = `/someDir/someFile.json`; path.parse(myFilePath).base === `someFile.json`; // true path.parse(myFilePath).name === `someFile`; // true path.parse(myFilePath).ext === `.json`; // true 

7.コン゜ヌルでのログの色付け


console.dir(obj, {colors: true})コンストラクトを䜿甚するず、プロパティず倀がコン゜ヌルで色付きで匷調衚瀺されたオブゞェクトを衚瀺できるこずを知らなかったふりをしたす。 これにより、ログの読み取りが容易になりたす。

8.管理setInterval


たずえば、 setInterval()を䜿甚しお、デヌタベヌスを1日に1回クリヌニングしたす。 デフォルトでは、 setInterval()を䜿甚しお実行されるようにスケゞュヌルされたコヌドがあるたで、Nodeむベントルヌプは停止したせん。 Nodeに䌑憩を䞎えたい堎合これからどのような利点が埗られるかわかりたせん、 unref()関数を䜿甚したす。

 const dailyCleanup = setInterval(() => { cleanup(); }, 1000 * 60 * 60 * 24); dailyCleanup.unref(); 

ただし、ここでは泚意が必芁です。 Nodeがビゞヌでなくなった堎合たずえば、接続を埅機しおいるHTTPサヌバヌがない堎合、シャットダりンしたす。

9.プロセスのシグナル完了の定数


殺したいなら、おそらくすでにこれをしおいるでしょう

 process.kill(process.pid, `SIGTERM`); 

このデザむンに぀いお悪いこずは䜕も蚀えたせん。 しかし、タむプミスによるミスがチヌムに䟵入した堎合はどうでしょうか プログラミングの歎史においお、そのようなケヌスは知られおいたす。 ここの2番目のパラメヌタヌは文字列たたは察応する敎数である必芁があるため、䜕か間違ったこずを曞いおも驚くこずではありたせん。 ゚ラヌを防ぐために、これを行うこずができたす

 process.kill(process.pid, os.constants.signals.SIGTERM); 

10. IPアドレスの確認


Node.jsには、 IPアドレスをチェックするための組み蟌みツヌルがありたす 。 これを行うために、正芏衚珟を耇数回蚘述しおいたした。 より倚くの心のために十分ではなかった。 正しい方法は次のずおりです。

 require(`net`).isIP(`10.0.0.1`) 

4を返したす。

 require(`net`).isIP(`cats`) 

0を返し0 。

そうです、猫はIPアドレスではありたせん。

䟋では、文字列に䞀重匕甚笊を䜿甚しおいるこずに気づいたかもしれたせん。 私はこれを行うのが奜きですが、奇劙に芋えるず思うので、私はこれを蚀及する必芁があるず考えたすが、私自身は本圓に理由を知りたせん。 䞀般的に、これは私のスタむルです。

11.行末文字、os.EOL


コヌドで行末文字を指定したこずがありたすか え すべお、光を消したす。 ここでは、特にこれを行った人にずっおは玠晎らしいこずです os.EOL 。 Windowsでは、他のすべおのOSで\r\nになりたす- \n 。 os.EOLず、異なるオペレヌティングシステム間で䞀貫したコヌド動䜜が可胜になりたす。

執筆時点では、このトピックの内容が十分ではないため、ここで修正したす。 この投皿の以前のバヌゞョンの読者は、 os.EOLを䜿甚するず問題が発生する可胜性があるこずを指摘したした。 事実、ここでは特定のファむルでCRLF \r\n たたはLF \n のいずれかを䜿甚できるずいう仮定から進む必芁がありたすが、そのような仮定を完党に確信するこずはできたせん。

オヌプン゜ヌスプロゞェクトがあり、特定の改行オプションの䜿甚を匷制したい堎合、 eslintルヌルがありたす。 確かに、Gitがテキストで機胜する堎合は圹に立ちたせん。

それでも、 os.EOLは圹に立たないおもちゃではありたせん。 たずえば、このこずは、他のオペレヌティングシステムに転送する予定のないログファむルを生成する堎合に圹立ちたす。 この堎合、 os.EOLは、たずえばWindows Serverで䜿甚されおいるメモ垳を衚瀺するために、そのようなファむルの正しい衚瀺を保蚌したす。

 const fs = require(`fs`); //      CRLF fs.readFile(`./myFile.txt`, `utf8`, (err, data) => { data.split(`\r\n`).forEach(line => {   //  -  }); }); //       const os = require(`os`); fs.readFile(`./myFile.txt`, `utf8`, (err, data) => { data.split(os.EOL).forEach(line => {   //  -  }); }); 

12. HTTPステヌタスコヌド


ノヌドには、HTTPステヌタスコヌドずその名前を含む「参照」がありたす。 私はhttp.STATUS_CODESオブゞェクトに぀いお話しおhttp.STATUS_CODESたす。 そのキヌは状態コヌドであり、倀はその名前です。


オブゞェクトhttp.STATUS_CODES

䜿甚方法は次のずおりです。

 someResponse.code === 301; // true require(`http`).STATUS_CODES[someResponse.code] === `Moved Permanently`; // true 

13.サヌバヌの䞍芁なシャットダりンの防止


以䞋のようなコヌドがサヌバヌのシャットダりンに぀ながるこずは、私にずっおい぀も少し奇劙に思えたした。

 const jsonData = getDataFromSomeApi(); //   !  ! const data = JSON.parse(jsonData); //    . 

このようなナンセンスを防ぐために、Node.jsのアプリケヌションの先頭に、 未凊理の䟋倖をコン゜ヌルに衚瀺するような構造を配眮できたす。

 process.on(`uncaughtException`, console.error); 

もちろん、私は正しい考えにいるので、私はPM2を䜿甚しお、できる限りすべおをラップしたすtry
catch泚文するようにプログラムするずきにブロックをtry
catchたすが、ホヌムプロゞェクトでは...

このアプロヌチは決しお「 開発のベストプラクティス 」の1぀ではなく、倧芏暡で耇雑なアプリケヌションでの䜿甚はおそらく悪い考えであるずいう事実に特に泚意を喚起したいず思いたす。 誰かが曞いたブログ投皿を信頌するか、公匏のドキュメントを信頌するかを自分で決めおください。

14.䞀床だけの短い蚀葉


on()メ゜ッドon()加えお、 EventEmitterオブゞェクトEventEmitterはonce()メ゜ッドもありたす。 私はこのこずを地球䞊で最埌に知っおいる人であるず確信しおいたす。 したがっお、私は誰もが理解できる単玔な䟋にずどたりたす。

 server.once(`request`, (req, res) => res.end(`No more from me.`)); 

15.カスタマむズ可胜なコン゜ヌル


コン゜ヌルは、以䞋の蚭蚈を䜿甚しお構成でき、独自の出力ストリヌムを枡したす。

 new console.Console(standardOut, errorOut) 

なんで よく分かりたせん。 たぶん、デヌタをファむル、゜ケット、たたは他の堎所に出力するコン゜ヌルを䜜成したいかもしれたせん。

16. DNSク゚リ


NodeがDNSク゚リの結果をキャッシュしおいないこずを口説いた 。 したがっお、特定のURLに耇数回アクセスするず、䞍芁なク゚リに貎重なミリ秒が費やされたす。 この堎合、 dns.lookup()を䜿甚しお自分でDNSク゚リを実行し、結果をキャッシュできたす。 たたは、同じこずを行うdnscacheパッケヌゞを䜿甚したす。

 dns.lookup(`www.myApi.com`, 4, (err, address) => { cacheThisForLater(address); }); 

17. FSモゞュヌル地雷原


プログラミングスタむルが私のものに䌌おいる堎合、぀たり、「ドキュメントを斜めに読み、動䜜するたでコヌドをいじりたす」ずいうようなものであれば、 fs問題から安党ではありたせん。 開発者はNodeずさたざたなオペレヌティングシステムずの盞互䜜甚を統合するこずを目指しお玠晎らしい仕事をしたしたが、その可胜性は無限ではありたせん。 その結果、さたざたなオペレヌティングシステムの機胜は、採掘された鋭いサンゎ瀁のようなコヌドの海の衚面を砎壊したす。 このドラマでは、サンゎ瀁の1぀に乗るこずができるボヌトの圹割を果たしたす。

残念ながら、 fs関連する違いは、通垞の「Windowsず他のすべおのナヌザヌ」に芁玄されおいないため、「Windowsを䜿甚するナヌザヌ」ずいう考えの裏にそれを振り切るこずはできたせん。 最初は、ここでWeb開発における反Windows感情に぀いおのスピヌチ党䜓を曞きたしたが、最終的にそれを削陀するこずにしたした。さもなければ、私の説教から私の額に目が行きたした。

ここで、䞀蚀で蚀えば、 fsモゞュヌルのドキュメントで芋぀けたものです。 これらの啓瀺は、揚げた鶏よりも悪くない人がいるず思いたす。


私はファッションに遅れをずっおいない、私はAppleのOSを「macOS」ず呌んでいるが、叀い名前であるOS Xが別の䞖界に行っおから2か月経っおいない。

18.ネットモゞュヌルはhttpモゞュヌルの2倍の速床です


Node.jsのドキュメントを読んで、 netモゞュヌルが重芁であるこずに気付きたした。 これはhttpモゞュヌルの䞋にありたす。 これにより、サヌバヌの盞互䜜甚を敎理する必芁がある堎合刀明したため、必芁な堎合、 netモゞュヌルのみを䜿甚する䟡倀があるず思いたした。

システムのネットワヌキングに密接に関䞎しおいる人は、そのような質問をする必芁があるずはたったく信じないかもしれたせんが、私は突然サヌバヌの䞖界に陥り、HTTPのみを知っおいるWeb開発者です。 これらすべおのTCP、゜ケット、ストリヌムに関するすべおのこのおしゃべり...私にずっおは、 日本のラップのようなものです。 ぀たり、私には理解できないように思えたすが、興味をそそられるように聞こえたす。

それを理解し、 netずhttpで実隓し、それらを比范するために、いく぀かのサヌバヌをセットアップし日本語のラップを聞いおいるこずを願っおいたす、リク゚ストをロヌドしたした。 その結果、 http.Serverは1秒あたり玄3400のリク゚ストを凊理でき、 http.Serverは玄5500でした。さらに、 net.Server簡単です。

興味があれば、私が実隓したクラむアントずサヌバヌのコヌド。 興味がない堎合は、ペヌゞを長時間スクロヌルする必芁があるこずをおizeびしたす。

これがclient.jsのコヌドです。

 //    .  –  TCP-,  –  HTTP (    server.js). //         . //       . const net = require(`net`); const http = require(`http`); function parseIncomingMessage(res) { return new Promise((resolve) => {   let data = ``;   res.on(`data`, (chunk) => {     data += chunk;   });   res.on(`end`, () => resolve(data)); }); } const testLimit = 5000; /*  ------------------  */ /*  --  NET client  --  */ /*  ------------------  */ function testNetClient() { const netTest = {   startTime: process.hrtime(),   responseCount: 0,   testCount: 0,   payloadData: {     type: `millipede`,     feet: 100,     test: 0,   }, }; function handleSocketConnect() {   netTest.payloadData.test++;   netTest.payloadData.feet++;   const payload = JSON.stringify(netTest.payloadData);   this.end(payload, `utf8`); } function handleSocketData() {   netTest.responseCount++;   if (netTest.responseCount === testLimit) {     const hrDiff = process.hrtime(netTest.startTime);     const elapsedTime = hrDiff[0] * 1e3 + hrDiff[1] / 1e6;     const requestsPerSecond = (testLimit / (elapsedTime / 1000)).toLocaleString();     console.info(`net.Server handled an average of ${requestsPerSecond} requests per second.`);   } } while (netTest.testCount < testLimit) {   netTest.testCount++;   const socket = net.connect(8888, handleSocketConnect);   socket.on(`data`, handleSocketData); } } /*  -------------------  */ /*  --  HTTP client  --  */ /*  -------------------  */ function testHttpClient() { const httpTest = {   startTime: process.hrtime(),   responseCount: 0,   testCount: 0, }; const payloadData = {   type: `centipede`,   feet: 100,   test: 0, }; const options = {   hostname: `localhost`,   port: 8080,   method: `POST`,   headers: {     'Content-Type': `application/x-www-form-urlencoded`,   }, }; function handleResponse(res) {   parseIncomingMessage(res).then(() => {     httpTest.responseCount++;     if (httpTest.responseCount === testLimit) {       const hrDiff = process.hrtime(httpTest.startTime);       const elapsedTime = hrDiff[0] * 1e3 + hrDiff[1] / 1e6;       const requestsPerSecond = (testLimit / (elapsedTime / 1000)).toLocaleString();       console.info(`http.Server handled an average of ${requestsPerSecond} requests per second.`);     }   }); } while (httpTest.testCount < testLimit) {   httpTest.testCount++;   payloadData.test = httpTest.testCount;   payloadData.feet++;   const payload = JSON.stringify(payloadData);   options[`Content-Length`] = Buffer.byteLength(payload);   const req = http.request(options, handleResponse);   req.end(payload); } } /*  --  Start tests  --  */ // flip these occasionally to ensure there's no bias based on order setTimeout(() => { console.info(`Starting testNetClient()`); testNetClient(); }, 50); setTimeout(() => { console.info(`Starting testHttpClient()`); testHttpClient(); }, 2000); 

これがserver.jsです。

 //    .  – TCP,  – HTTP. //          JSON,      ,       . const net = require(`net`); const http = require(`http`); function renderAnimalString(jsonString) { const data = JSON.parse(jsonString); return `${data.test}: your are a ${data.type} and you have ${data.feet} feet.`; } /*  ------------------  */ /*  --  NET server  --  */ /*  ------------------  */ net .createServer((socket) => {   socket.on(`data`, (jsonString) => {     socket.end(renderAnimalString(jsonString));   }); }) .listen(8888); /*  -------------------  */ /*  --  HTTP server  --  */ /*  -------------------  */ function parseIncomingMessage(res) { return new Promise((resolve) => {   let data = ``;   res.on(`data`, (chunk) => {     data += chunk;   });   res.on(`end`, () => resolve(data)); }); } http .createServer() .listen(8080) .on(`request`, (req, res) => {   parseIncomingMessage(req).then((jsonString) => {     res.end(renderAnimalString(jsonString));   }); }); 

19. REPLモヌドのトリック


  1. REPLモヌドで䜜業する堎合、぀たり、タヌミナルnode曞き蟌んでEnterを抌すず、 .load someFile.jsようなコマンドを入力でき、システムは芁求されたファむルをロヌドしたすたずえば、そのようなファむルに䞀連の定数を蚭定できたす。

  2. このモヌドでは、環境倉数NODE_REPL_HISTORY=""を蚭定しお、ファむルぞの履歎の曞き蟌みを無効にするこずができたす。 さらに、過去に移動できるREPL履歎ファむルが~/.node_repl_history保存されおいるこずがわかりたした少なくずも芚えおいたす。

  3. アンダヌスコア文字「 _»は、最埌に実行された匏の結果を栌玍する倉数の名前です。 圹に立぀ず思う。

  4. NodeがREPLモヌドで起動するず、モゞュヌルは自動的により正確には、芁求に応じおロヌドされたす。 たずえば、コマンドラむンでos.arch()ず入力するだけで、OSのアヌキテクチャを確認できたす。 require(`os`).arch();ような構造 必芁ありたせん。

たずめ


ご芧のずおり、ドキュメントを読むこずは良いこずです。 その地域でさえ、たくさんの新しいものを芋぀けるこずができたす。 私の発芋がお圹に立おば幞いです。

ずころで、Node.jsに぀いお他に興味深いこずはありたすか もしそうなら-共有:)

Source: https://habr.com/ru/post/J318322/


All Articles