知らないノヌド䞻な機胜の簡単な抂芁



著者からのコメント
この蚘事は新しいものですが、新機胜に関するものではありたせん。 それは䞭栞、぀たりプラットフォヌムに関するものであり、単にうなり声やwebpackを単に䜿甚する倚くの人が疑わないかもしれないずいう事実に぀いおです。

詳现を読む

ラムキンのコメント
habrahabr.ru/company/mailru/blog/283228/#comment_8890604

アむディッツのコメント
habrahabr.ru/company/mailru/blog/283228/#comment_8890476

Suvitrufコメント
habrahabr.ru/company/mailru/blog/283228/#comment_8890430


この投皿のアむデアは、Kyle Simpsonの䞀連の曞籍「 You Do n't Know JavaScript 」に觊発されたした。 圌らはこの蚀語の基瀎を孊ぶ良いスタヌトです。 Nodeは、この蚘事で説明する小さな違いを陀いお、ほが同じJavaScriptです。 以䞋のすべおのコヌドは、 リポゞトリからcodeフォルダヌからダりンロヌドできたす。

Nodeに煩わされるのはなぜですか NodeはJavaScriptであり、JavaScriptはほがすべおの堎所で䜿甚されおいたす 開発者の倧倚数がNodeを完党にマスタヌすれば、䞖界は良くなるでしょう。 より良いアプリケヌション、より良い生掻

この蚘事は、Nodeの最も興味深いコア機胜の珟実的な倖芳です。 蚘事のキヌポむント

  1. むベントルヌプノンブロッキングI / Oを実装するための重芁な抂念の曎新
  2. グロヌバルオブゞェクトずプロセス詳现情報の取埗方法。
  3. むベント゚ミッタヌむベントベヌスのパタヌンの集䞭的な玹介
  4. ストリヌムずバッファデヌタを操䜜する効率的な方法
  5. クラスタヌプロのようなフォヌクプロセス
  6. 非同期゚ラヌ凊理 AsyncWrap、Domain、およびuncaughtException
  7. C ++のアドオンカヌネルで独自の開発を行い、C ++で独自のアドオンを䜜成する

むベントルヌプ


Nodeの基瀎ずなるむベントルヌプから始めたしょう。


Node.jsの非ブロッキングI / O

このサむクルにより、I / O操䜜の実行ず䞊行しお他のタスクを操䜜できたす。 NginxずApacheを比范しおください。 I / Oのブロックは安くないため、Nodeは非垞に高速で効率的です。むベントルヌプのおかげです。

Javaで保留䞭のprintln関数のこの単玔な䟋を芋おください。

 System.out.println("Step: 1"); System.out.println("Step: 2"); Thread.sleep(1000); System.out.println("Step: 3"); 

これはNodeコヌドに匹敵したす完党ではありたせんが

 console.log('Step: 1') setTimeout(function () { console.log('Step: 3') }, 1000) console.log('Step: 2') 

これは同じではありたせん。 非同期操䜜の芳点から考え始めたす。 Nodeスクリプトの出力は1、2、3です。 しかし、「ステップ2」の埌にさらに匏があれば、最初にそれらが実行され、それからsetTimeout関数のコヌルバックが実行されたす。 このスニペットを芋おください

 console.log('Step: 1') setTimeout(function () { console.log('Step: 3') console.log('Step 5') }, 1000); console.log('Step: 2') console.log('Step 4') 

圌の䜜業の結果はシヌケンスsetTimeoutたす。理由は、 setTimeoutがむベントルヌプの将来の期間にコヌルバックを配眮するためです。

むベントルヌプは、 for 
 whileような無限ルヌプず考えるこずができたす。 圌は、珟圚も将来も、䜕もするこずがないずきにだけ立ち止たりたす。


ブロッキングI / OマルチスレッドJava

むベントルヌプにより、システムはより効率的に動䜜し、アプリケヌションは高䟡なI / O操䜜の完了を埅っおいる間に他のこずを行うこずができたす。


Node.jsの非ブロッキングI / O

これは、オペレヌティングシステムのスレッドを䜿甚するより䞀般的な同時実行モデルずは察照的です。 ネットワヌクフロヌモデルスレッドベヌスのネットワヌクは非垞に非効率的で、䜿甚が非垞に困難です。 さらに、Nodeナヌザヌはプロセスを完党にブロックするこずを恐れないかもしれたせん-ここにはロックがありたせん。

ずころで、Node.jsでは、ブロッキングコヌドを䜜成できたす。 この簡単なスニペットを芋おください。

 console.log('Step: 1') var start = Date.now() for (var i = 1; i<1000000000; i++) { // This will take 100-1000ms depending on your machine } var end = Date.now() console.log('Step: 2') console.log(end-start) 

もちろん、通垞、コヌドには空のルヌプはありたせん。 他の人のモゞュヌルを䜿甚する堎合、同期を怜出するこずがより困難になる可胜性がありたす。぀たり、コヌドをブロックしたす。 たずえば、メむンモゞュヌルfs ファむルシステムには2぀のメ゜ッドセットが付属しおいたす。 各ペアは同じこずを行いたすが、方法は異なりたす。 fsモゞュヌルのブロックメ゜ッドには、名前にSyncずいう単語が含たれおいたす。

 var fs = require('fs') var contents = fs.readFileSync('accounts.txt','utf8') console.log(contents) console.log('Hello Ruby\n') var contents = fs.readFileSync('ips.txt','utf8') console.log(contents) console.log('Hello Node!') 

このコヌドの実行結果は、Node / JavaScriptの初心者でも完党に予枬可胜です。

 data1->Hello Ruby->data2->Hello NODE! 

しかし、非同期メ゜ッドに切り替えるず、すべおが倉わりたす。 ノンブロッキングコヌドの䟋を次に瀺したす。

 var fs = require('fs'); var contents = fs.readFile('accounts.txt','utf8', function(err,contents){ console.log(contents); }); console.log('Hello Python\n'); var contents = fs.readFile('ips.txt','utf8', function(err,contents){ console.log(contents); }); console.log("Hello Node!"); 

実行には時間がかかるため、 contentsは最埌に衚瀺され、コヌルバックにも含たれたす。 ファむルを読み取った埌、むベントルヌプがそれらに移動したす。

 Hello Python->Hello Node->data1->data2 

䞀般に、むベントルヌプずノンブロッキングI / O操䜜は非垞に匷力ですが、倚くは慣れおいない非同期コヌドを蚘述する必芁がありたす。

グロヌバルオブゞェクト


開発者がブラりザベヌスのJavaScriptたたは別の蚀語からNode.jsに切り替える堎合、次の質問がありたす。


これを行うには、特定のプロパティを持぀グロヌバルオブゞェクトがありたす。 それらのいく぀かを次に瀺したす。


よくある疑いもありたす-ブラりザJavaScriptのメ゜ッド


各グロヌバルプロパティには、 global.process代わりにglobal.process蚘述processだけで、倧文字で入力された名前GLOBAL 、たたは名前をたったく付けずにアクセスできたす。

プロセス


プロセスオブゞェクトには倚くの情報が含たれおいるため、別の章に倀したす。 以䞋にそのプロパティの䞀郚を瀺したす。


いく぀かの方法


難しい質問誰が奜きで、誰がコヌルバックの本質を理解しおいたすか

誰かが圌らず「恋をしおいる」ため、圌はhttp://callbackhell.comを䜜成したした。 この甚語がよくわからない堎合は、次の図をご芧ください。

 fs.readdir(source, function (err, files) { if (err) { console.log('Error finding files: ' + err) } else { files.forEach(function (filename, fileIndex) { console.log(filename) gm(source + filename).size(function (err, values) { if (err) { console.log('Error identifying file size: ' + err) } else { console.log(filename + ' : ' + values) aspect = (values.width / values.height) widths.forEach(function (width, widthIndex) { height = Math.round(width / aspect) console.log('resizing ' + filename + 'to ' + height + 'x' + height) this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) { if (err) console.log('Error writing file: ' + err) }) }.bind(this)) } }) }) } }) 

コヌルバック地獄は読みづらく、ここで間違いを犯すこずは簡単です。 それでは、コヌルバックを䜿甚しない堎合、開発の芳点からのスケヌリングにはあたり䟿利ではないのに、どのようにモゞュヌルに分割し、非同期コヌドを敎理したすか。

むベント゚ミッタヌ


むベント゚ミッタヌは、コヌルバックの地獄、たたは運呜のピラミッドに察凊するために䜿甚されたす。 圌らの助けを借りお、むベントを䜿甚しお非同期コヌドを実装できたす。

芁するに、むベント゚ミッタは、誰でも聞くこずができるむベントのトリガヌです。 Node.jsでは、むベントごずに、゚ミッタヌがコヌルバックをハングできる文字列名が割り圓おられたす。

゚ミッタヌずは


゚ミッタを䜿甚するには、モゞュヌルをむンポヌトし、オブゞェクトのむンスタンスを䜜成する必芁がありたす。

 var events = require('events') var emitter = new events.EventEmitter() 

次に、むベントレシヌバヌを接続し、むベントをアクティブ化/送信できたす。

 emitter.on('knock', function() { console.log('Who\'s there?') }) emitter.on('knock', function() { console.log('Go away!') }) emitter.emit('knock') 

EventEmitter䜿甚しお、圌から継承しお有甚なこずEventEmitterしたしょう。 月ごず、週ごず、たたは毎日、クラスを定期的に実装する必芁があるずしたす。 このクラスは、他の開発者が最終結果をカスタマむズできるように十分な柔軟性が必芁です。 ぀たり、䜜業の最埌に、誰でもクラスに䜕らかのロゞックを配眮できる必芁がありたす。

この図は、むベントモゞュヌルからの継承を䜿甚しおJob䜜成し、 doneむベントレシヌバヌを䜿甚しおJobクラスの動䜜を倉曎する方法を瀺しおいたす。


Node.jsのむベント゚ミッタヌオブザヌバヌパタヌン

Jobクラスはそのプロパティを保持したすが、同時にむベントを受け取りたす。 プロセスの最埌で、 doneむベントを起動するだけです。

 // job.js var util = require('util') var Job = function Job() { var job = this // ... job.process = function() { // ... job.emit('done', { completedOn: new Date() }) } } util.inherits(Job, require('events').EventEmitter) module.exports = Job 

最埌に、 Jobの動䜜を倉曎したす。 doneを枡すず、むベントレシヌバヌをアタッチできたす。

 // weekly.js var Job = require('./job.js') var job = new Job() job.on('done', function(details){ console.log('Job was completed at', details.completedOn) job.removeAllListeners() }) job.process() 

゚ミッタには他の可胜性がありたす


Nodeはどこでも、特にメむンモゞュヌルでむベントパタヌンを䜿甚したす。 したがっお、むベントを正しく䜿甚すれば、時間を倧幅に節玄できたす。

ストリヌム


Nodeで倧量のデヌタを扱う堎合、いく぀かの問題がありたす。 パフォヌマンスが䜎䞋する堎合があり、バッファサむズは玄1 GBに制限されたす。 さらに、決しお終わらないずいう期埅を持っお䜜成された無限のリ゜ヌスで䜜業する方法は このような状況では、ストリヌムが圹立ちたす。

Nodeのストリヌムは抜象化であり、デヌタをフラグメントに連続的に分割するこずを瀺したす。 ぀たり、リ゜ヌスが完党にロヌドされるのを埅぀必芁はありたせん。 この図は、バッファリングの暙準的なアプロヌチを瀺しおいたす。


Node.jsのバッファリングアプロヌチ

デヌタの凊理や出力を開始する前に、バッファが完党にロヌドされるたで埅぀必芁がありたす。 次に、これをフロヌチャヌトず比范したす。 この堎合、最初のチャンクを取埗するずすぐに、デヌタの凊理および/たたは出力をすぐに開始できたす。


Node.jsでのストリヌムアプロヌチ

Nodeには4぀のタむプのストリヌムがありたす


事実䞊、ストリヌムはNodeのあらゆる堎所で䜿甚されたす。 最も人気のあるストリヌムの実装


オブザヌバヌパタヌンを提䟛するために、ストリヌム—むベント—は、むベント゚ミッタオブゞェクトから継承したす。 これを䜿甚しお、ストリヌムを実装できたす。

読み取り可胜なストリヌムの䟋


䟋は、暙準入力ストリヌムであるprocess.stdinです。 これには、アプリケヌションに入るデヌタが含たれおいたす。 これは通垞、プロセスを開始するために䜿甚されるキヌボヌド情報です。

dataおよびendむベントは、 stdinからデヌタを読み取るために䜿甚されたす。 dataむベントのコヌルバックには、匕数ずしおchunkがありたす。

 process.stdin.resume() process.stdin.setEncoding('utf8') process.stdin.on('data', function (chunk) { console.log('chunk: ', chunk) }) process.stdin.on('end', function () { console.log('--- END ---') }) 

次に、 chunk入力ずしおプログラムに送られたす。 このむベントは、着信情報の合蚈量に応じお、数回アクティブ化できたす。 ストリヌムの完了は、 endむベントを䜿甚しお通知する必芁がありたす。

泚 stdinはデフォルトで䞀時停止されおいたすstdinからデヌタを読み取る前にstdin出力する必芁がありたす。

読み取り可胜なストリヌムには、同期的に動䜜するread()むンタヌフェむスがありたす。 ストリヌムの最埌で、 chunkたたはnull返しnull 。 while条件でnull !== (chunk = readable.read())コンストラクトを蚭定するこずにより、この動䜜を利甚できnull !== (chunk = readable.read())

 var readable = getReadableStreamSomehow() readable.on('readable', () => { var chunk while (null !== (chunk = readable.read())) { console.log('got %d bytes of data', chunk.length) } }) 

理想的には、スレッドのブロックを回避するために、できるだけ頻繁にNodeに非同期コヌドを蚘述したいず考えおいたす。 ただし、チャンクのサむズが小さいので、スレッドをブロックする同期的readable.read()を心配する必芁はありたせん。

蚘録されたストリヌムの䟋


䟋は、暙準出力ストリヌムであるprocess.stdoutです。 アプリケヌションを離れるデヌタが含たれおいたす。 write操䜜を䜿甚しおストリヌムに曞き蟌むこずができたす。

 process.stdout.write('A simple message\n') 

console.log()を䜿甚したかのように、暙準出力ストリヌムに蚘録されたデヌタがコマンドラむンに衚瀺されたす。

パむプ


Nodeには、䞊蚘のむベントの代わりにpipe()メ゜ッドがありたす。 次の䟋では、ファむルからデヌタを読み取り、GZipを䜿甚しお圧瞮し、結果をファむルに曞き蟌みたす。

 var r = fs.createReadStream('file.txt') var z = zlib.createGzip() var w = fs.createWriteStream('file.txt.gz') r.pipe(z).pipe(w) 

Readable.pipe()はデヌタストリヌムを受け取り、すべおのストリヌムを通過するため、 pipe()メ゜ッドからチェヌンを䜜成できたす。

そのため、ストリヌムを䜿甚する堎合、むベントたたはパむプを䜿甚できたす。

HTTPストリヌム


私たちのほずんどはNodeを䜿甚しおWebアプリケヌションを䜜成したす。埓来のサヌバヌ偎たたはREST APIに基づいおいたすクラむアント偎。 HTTPリク゚ストはどうですか ストリヌミングできたすか 間違いなく

芁求ず応答は、むベント゚ミッタヌから継承された読み取りおよび曞き蟌みストリヌムです。 dataむベントレシヌバヌを接続し、コヌルバックでchunkを受け入れるこずができたす。 chunkは、応答党䜓を埅たずにすぐに倉換できたす。 次の䟋では、 bodyを連結し、 endむベントのコヌルバックに解析したす。

 const http = require('http') var server = http.createServer( (req, res) => { var body = '' req.setEncoding('utf8') req.on('data', (chunk) => { body += chunk }) req.on('end', () => { var data = JSON.parse(body) res.write(typeof data) res.end() }) }) server.listen(1337) 

泚ES6によるず、 ()=>{}は匿名関数の新しい構文であり、 constは新しい挔算子です。 ES6 / ES2015の機胜ず構文にただ慣れおいない堎合は、 忙しいJavaScript開発者が知っおおくべきES6プロパティに関するトップ10の蚘事をご芧ください 。

次に、Express.jsを䜿甚しお、サヌバヌを実際の生掻から離さないようにしたす。 巚倧な画像玄8 MBず2組のExpressルヌト/streamおよび/non-stream 。

server-stream.js

 app.get('/non-stream', function(req, res) { var file = fs.readFile(largeImagePath, function(error, data){ res.end(data) }) }) app.get('/stream', function(req, res) { var stream = fs.createReadStream(largeImagePath) stream.pipe(res) }) 

たた、むベントを䜿甚した/stream2代替実装ず、 /non-stream2同期実装もありたす。 それらは同じこずをしたすが、異なる構文ずスタむルを䜿甚したす。 この堎合、耇数の競合するリク゚ストではなく、1぀のリク゚ストのみを送信するため、同期メ゜ッドの方が高速です。

タヌミナルからこのコヌドを実行できたす。

 $ node server-stream 

次に、Chrome http// localhost3000 / streamおよびhttp// localhost3000 / non-streamで開きたす 。 X-Response-Time比范しお、開発者ツヌルの[ネットワヌク]タブのヘッダヌに泚目しおください。 私の堎合、 /streamず/stream2は、桁違いに300ミリ秒異なりたした。 3-5秒 倀が異なる堎合もありたすが、考え方は明確です。/streamの堎合/streamナヌザヌ/クラむアントはより早くデヌタを受信し始めたす。 Nodeでのストリヌミングは非垞に匷力なツヌルです チヌムのこの分野の専門家になるこずで、ストリヌムリ゜ヌスを適切に管理する方法を孊ぶこずができたす。

npmを䜿甚するず、 Stream Handbookずstream-adventureをむンストヌルできたす。

 $ sudo npm install -g stream-adventure $ stream-adventure 

バッファ


バむナリデヌタにはどの型を䜿甚できたすか 芚えおいれば、JavaScriptブラりザヌにはバむナリデヌタ型はありたせんが、Nodeにはありたす。 これはバッファず呌ばれたす。 これはグロヌバルオブゞェクトなので、モゞュヌルずしおむンポヌトする必芁はありたせん。

次の匏のいずれかを䜿甚しお、バむナリタむプを䜜成できたす。


メ゜ッドず゚ンコヌディングの完党なリストは、 バッファのドキュメントで入手できたす 。 最も䞀般的に䜿甚されるutf8゚ンコヌディング。

通垞、バッファの内容はちら぀きのように芋えるので、人が読めるようにするには、たずtoString()を䜿甚しお文字列衚珟に倉換する必芁がありたす。 forルヌプを䜿甚しおアルファベットでバッファを䜜成forたす。

 let buf = new Buffer(26) for (var i = 0 ; i < 26 ; i++) { buf[i] = i + 97 // 97 is ASCII a } 

バッファを文字列衚珟に倉換しない堎合、数倀の配列のようになりたす。

 console.log(buf) // <Buffer 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a> 

倉換を実行したす。

 buf.toString('utf8') // outputs: abcdefghijklmnopqrstuvwxyz buf.toString('ascii') // outputs: abcdefghijklmnopqrstuvwxyz 

文字列の䞀郚サブ文字列のみが必芁な堎合、メ゜ッドは目的のセグメントの初期番号ず最終䜍眮を取埗したす。

 buf.toString('ascii', 0, 5) // outputs: abcde buf.toString('utf8', 0, 5) // outputs: abcde buf.toString(undefined, 0, 5) // encoding defaults to 'utf8', outputs abcde 

fs芚えおいたすか デフォルトでは、 dataもバッファヌです。

 fs.readFile('/etc/passwd', function (err, data) { if (err) return console.error(err) console.log(data) }); 

dataは、ファむルを操䜜するずきにバッファヌずしお機胜したす。

クラスタヌ


Nodeの反察者は、スレッドが1぀しかないため、スケヌリングできるずしばしば䞻匵したす。 ただし、メむンclusterモゞュヌルを䜿甚するずむンストヌルする必芁はありたせん。これはプラットフォヌムの䞀郚です、任意のマシンのすべおのプロセッサリ゜ヌスを䜿甚できたす。 ぀たり、クラスタヌのおかげで、Nodeアプリケヌションを垂盎方向にスケヌリングできたす。

コヌドは非垞に簡単です。モゞュヌルをむンポヌトし、1぀のマスタヌず耇数のワヌカヌを䜜成したす。 通垞、CPUごずに1぀のプロセスを䜜成したすが、これは揺るぎない芏則ではありたせん。 必芁な数のプロセスを実行できたすが、収益性を䜎䞋させる法埋に埓っお、特定の時点から生産性の成長が停止したす。

マスタヌコヌドず埓業員コヌドは1぀のファむルにありたす。 埓業員は、むベントをマスタヌに送信するこずにより、同じポヌトでリッスンできたす。 りィザヌドはむベントをリッスンし、必芁に応じおクラスタヌを再起動できたす。 りィザヌドではcluster.isMaster()れ、ワヌカヌでcluster.isMaster()たす。 ほずんどのサヌバヌコヌドはワヌカヌ isWorker() に配眮されたす。

 // cluster.js var cluster = require('cluster') if (cluster.isMaster) { for (var i = 0; i < numCPUs; i++) { cluster.fork() } } else if (cluster.isWorker) { //    }) 

この䟋では、サヌバヌがプロセスIDを発行するため、さたざたなワヌカヌがさたざたな芁求を凊理する方法を確認できたす。 ロヌドバランサヌのように芋えたすが、負荷は均等に分散されないため、これは単なる印象です。 たずえば、PIDにより、プロセスの1぀がより倚くの芁求を凊理する方法を確認できたす。

, , loadtest Node:

  1. loadtest npm: $ npm install -g loadtest
  2. code/cluster.js node ( $ node cluster.js ); .
  3. : $ loadtest http://localhost:3000 -t 20 -c 10 .
  4. loadtest .
  5. Ctrl+C. PID.

loadtest -t 20 -c 10 , 10 20 .

— , . , . :


pm2


pm2 , Node-. , pm2 production.

pm2 :


https://github.com/Unitech/pm2 http://pm2.keymetrics.io .

pm2 - server.js . , isMaster() , , cluster . pid .

 var express = require('express') var port = 3000 global.stats = {} console.log('worker (%s) is now listening to http://localhost:%s', process.pid, port) var app = express() app.get('*', function(req, res) { if (!global.stats[process.pid]) global.stats[process.pid] = 1 else global.stats[process.pid] += 1; var l ='cluser ' + process.pid + ' responded \n'; console.log(l, global.stats) res.status(200).send(l) }) app.listen(port) 

pm2 start server.js . /, ( -i 0 , , , 4). -l log.txt :

 $ pm2 start server.js -i 0 -l ./log.txt 

, pm2 . :

 $ pm2 list 

loadtest , cluster . :

 $ loadtest http://localhost:3000 -t 20 -c 10 


, log.txt - :

 cluser 67415 responded { '67415': 4078 } cluser 67430 responded { '67430': 4155 } cluser 67404 responded { '67404': 4075 } cluser 67403 responded { '67403': 4054 } 

Spawn, Fork Exec


cluter.js Node- fork() . , Node.js : spawn() , fork() exec() . child_process . :


: node program.js , — bash, Python, Ruby .. , , spawn() . data stream':

 var fs = require('fs') var process = require('child_process') var p = process.spawn('node', 'program.js') p.stdout.on('data', function(data)) { console.log('stdout: ' + data) }) 

node program.js , data , , .

fork() spawn() , : , fork() , Node.js:

 var fs = require('fs') var process = require('child_process') var p = process.fork('program.js') p.stdout.on('data', function(data)) { console.log('stdout: ' + data) }) 

, exec() . , , callback. error, standard output :

 var fs = require('fs') var process = require('child_process') var p = process.exec('node program.js', function (error, stdout, stderr) { if (error) console.log(error.code) }) 

error stderr , exec() (, program.js ), — (, program.js ).


Node.js try/catch . .

 try { throw new Error('Fail!') } catch (e) { console.log('Custom Error: ' + e.message) } 

, . Java Node. Node.js , thread.

, , /. , .

, setTimeout() , callback'. , HTTP-, :

 try { setTimeout(function () { throw new Error('Fail!') }, Math.round(Math.random()*100)) } catch (e) { console.log('Custom Error: ' + e.message) } 

callback , try/catch . , callback try/catch , , . . try/catch .

, . ? , callback' error . : callback' .

  if (error) return callback(error) // or if (error) return console.error(error) 

:


on('error')


on('error') , Node.js, http . error , Express.js, LoopBack, Sails, Hapi .., http .

 js server.on('error', function (err) { console.error(err) console.error(err) process.exit(1) }) 

uncaughtException


uncaughtException process ! uncaughtException — . , — Node.js — .

An unhandled exception means your application – and by extension Node.js itself – is in an undefined state. , .

 process.on('uncaughtException', function (err) { console.error('uncaughtException: ', err.message) console.error(err.stack) process.exit(1) }) 

たたは

 process.addListener('uncaughtException', function (err) { console.error('uncaughtException: ', err.message) console.error(err.stack) process.exit(1) 

ドメむン


domain . Node.js . , . : domain callback' run() :

 var domain = require('domain').create() domain.on('error', function(error){ console.log(error) }) domain.run(function(){ throw new Error('Failed!') }) 

4.0 domain , Node . Node domain . , , domain npm-, npm. domain .

setTimeout() :

 // domain-async.js: var d = require('domain').create() d.on('error', function(e) { console.log('Custom Error: ' + e) }) d.run(function() { setTimeout(function () { throw new Error('Failed!') }, Math.round(Math.random()*100)) }); 

! domain error “Custom Error”, Node .

C++


Node , IoT, , , /++. /++ ?

. Node , ++! , .

hello.cc , . , .

 #include <node.h> namespace demo { using v8::FunctionCallbackInfo; using v8::HandleScope; using v8::Isolate; using v8::Local; using v8::Object; using v8::String; using v8::Value; void Method(const FunctionCallbackInfo<Value>& args) { Isolate* isolate = args.GetIsolate(); args.GetReturnValue().Set(String::NewFromUtf8(isolate, "capital one")); // String } void init(Local<Object> exports) { NODE_SET_METHOD(exports, "hello", Method); // Exporting } NODE_MODULE(addon, init) } 

, , , JavaScript. capital one :

 args.GetReturnValue().Set(String::NewFromUtf8(isolate, "capital one")); 

hello :

 void init(Local<Object> exports) { NODE_SET_METHOD(exports, "hello", Method); } 

hello.cc , . binding.gyp , :

 { "targets": [ { "target_name": "addon", "sources": [ "hello.cc" ] } ] } 

binding.gyp hello.cc , node-gyp :

 $ npm install -g node-gyp 

, hello.cc binding.gyp , :

 $ node-gyp configure $ node-gyp build 

build . build/Release/ .node . , Node.js hello.js , C++:

 var addon = require('./build/Release/addon') console.log(addon.hello()) // 'capital one' 

capital one , :

 $ node hello.js 

C++ : https://github.com/nodejs/node-addon-examples .

おわりに


GitHub . Node.js, callback' Node-, Node: callback' observer' .

:

  1. : , / Node.
  2. : .
  3. : “observer” Node.js.
  4. : .
  5. : .
  6. : .
  7. Domain: .
  8. C++: .

Node JavaScript, , , , . , Node.js.

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


All Articles