最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在nodejs中創(chuàng)建child process的方法

 更新時(shí)間:2021年01月26日 09:37:10   作者:flydean程序那些事  
這篇文章主要介紹了在nodejs中創(chuàng)建child process的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

簡(jiǎn)介

nodejs的main event loop是單線程的,nodejs本身也維護(hù)著Worker Pool用來(lái)處理一些耗時(shí)的操作,我們還可以通過(guò)使用nodejs提供的worker_threads來(lái)手動(dòng)創(chuàng)建新的線程來(lái)執(zhí)行自己的任務(wù)。

本文將會(huì)介紹一種新的執(zhí)行nodejs任務(wù)的方式,child process。

child process

lib/child_process.js提供了child_process模塊,通過(guò)child_process我們可以創(chuàng)建子進(jìn)程。

注意,worker_threads創(chuàng)建的是子線程,而child_process創(chuàng)建的是子進(jìn)程。

在child_process模塊中,可以同步創(chuàng)建進(jìn)程也可以異步創(chuàng)建進(jìn)程。同步創(chuàng)建方式只是在異步創(chuàng)建的方法后面加上Sync。

創(chuàng)建出來(lái)的進(jìn)程用ChildProcess類來(lái)表示。

我們看下ChildProcess的定義:

interface ChildProcess extends events.EventEmitter {
 stdin: Writable | null;
 stdout: Readable | null;
 stderr: Readable | null;
 readonly channel?: Pipe | null;
 readonly stdio: [
  Writable | null, // stdin
  Readable | null, // stdout
  Readable | null, // stderr
  Readable | Writable | null | undefined, // extra
  Readable | Writable | null | undefined // extra
 ];
 readonly killed: boolean;
 readonly pid: number;
 readonly connected: boolean;
 readonly exitCode: number | null;
 readonly signalCode: NodeJS.Signals | null;
 readonly spawnargs: string[];
 readonly spawnfile: string;
 kill(signal?: NodeJS.Signals | number): boolean;
 send(message: Serializable, callback?: (error: Error | null) => void): boolean;
 send(message: Serializable, sendHandle?: SendHandle, callback?: (error: Error | null) => void): boolean;
 send(message: Serializable, sendHandle?: SendHandle, options?: MessageOptions, callback?: (error: Error | null) => void): boolean;
 disconnect(): void;
 unref(): void;
 ref(): void;

 /**
  * events.EventEmitter
  * 1. close
  * 2. disconnect
  * 3. error
  * 4. exit
  * 5. message
  */
 ...
 }

可以看到ChildProcess也是一個(gè)EventEmitter,所以它可以發(fā)送和接受event。

ChildProcess可以接收到event有5種,分別是close,disconnect,error,exit和message。

當(dāng)調(diào)用父進(jìn)程中的 subprocess.disconnect() 或子進(jìn)程中的 process.disconnect() 后會(huì)觸發(fā) disconnect 事件。

當(dāng)出現(xiàn)無(wú)法創(chuàng)建進(jìn)程,無(wú)法kill進(jìn)程和向子進(jìn)程發(fā)送消息失敗的時(shí)候都會(huì)觸發(fā)error事件。

當(dāng)子進(jìn)程結(jié)束后時(shí)會(huì)觸發(fā)exit事件。

當(dāng)子進(jìn)程的 stdio 流被關(guān)閉時(shí)會(huì)觸發(fā) close 事件。 注意,close事件和exit事件是不同的,因?yàn)槎鄠€(gè)進(jìn)程可能共享同一個(gè)stdio,所以發(fā)送exit事件并不一定會(huì)觸發(fā)close事件。

看一個(gè)close和exit的例子:

const { spawn } = require('child_process');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
 console.log(`stdout: ${data}`);
});

ls.on('close', (code) => {
 console.log(`子進(jìn)程使用代碼 $[code] 關(guān)閉所有 stdio`);
});

ls.on('exit', (code) => {
 console.log(`子進(jìn)程使用代碼 $[code] 退出`);
});

最后是message事件,當(dāng)子進(jìn)程使用process.send() 發(fā)送消息的時(shí)候就會(huì)被觸發(fā)。

ChildProcess中有幾個(gè)標(biāo)準(zhǔn)流屬性,分別是stderr,stdout,stdin和stdio。

stderr,stdout,stdin很好理解,分別是標(biāo)準(zhǔn)錯(cuò)誤,標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)輸入。

我們看一個(gè)stdout的使用:

const { spawn } = require('child_process');

const subprocess = spawn('ls');

subprocess.stdout.on('data', (data) => {
 console.log(`接收到數(shù)據(jù)塊 ${data}`);
});

stdio實(shí)際上是stderr,stdout,stdin的集合:

readonly stdio: [
  Writable | null, // stdin
  Readable | null, // stdout
  Readable | null, // stderr
  Readable | Writable | null | undefined, // extra
  Readable | Writable | null | undefined // extra
 ];

其中stdio[0]表示的是stdin,stdio[1]表示的是stdout,stdio[2]表示的是stderr。

如果在通過(guò)stdio創(chuàng)建子進(jìn)程的時(shí)候,這三個(gè)標(biāo)準(zhǔn)流被設(shè)置為除pipe之外的其他值,那么stdin,stdout和stderr將為null。

我們看一個(gè)使用stdio的例子:

const assert = require('assert');
const fs = require('fs');
const child_process = require('child_process');

const subprocess = child_process.spawn('ls', {
 stdio: [
 0, // 使用父進(jìn)程的 stdin 用于子進(jìn)程。
 'pipe', // 把子進(jìn)程的 stdout 通過(guò)管道傳到父進(jìn)程 。
 fs.openSync('err.out', 'w') // 把子進(jìn)程的 stderr 定向到一個(gè)文件。
 ]
});

assert.strictEqual(subprocess.stdio[0], null);
assert.strictEqual(subprocess.stdio[0], subprocess.stdin);

assert(subprocess.stdout);
assert.strictEqual(subprocess.stdio[1], subprocess.stdout);

assert.strictEqual(subprocess.stdio[2], null);
assert.strictEqual(subprocess.stdio[2], subprocess.stderr);

通常情況下父進(jìn)程中維護(hù)了一個(gè)對(duì)子進(jìn)程的引用計(jì)數(shù),只有在當(dāng)子進(jìn)程退出之后父進(jìn)程才會(huì)退出。

這個(gè)引用就是ref,如果調(diào)用了unref方法,則允許父進(jìn)程獨(dú)立于子進(jìn)程退出。

const { spawn } = require('child_process');

const subprocess = spawn(process.argv[0], ['child_program.js'], {
 detached: true,
 stdio: 'ignore'
});

subprocess.unref();

最后,我們看一下如何通過(guò)ChildProcess來(lái)發(fā)送消息:

subprocess.send(message[, sendHandle[, options]][, callback])

其中message就是要發(fā)送的消息,callback是發(fā)送消息之后的回調(diào)。

sendHandle比較特殊,它可以是一個(gè)TCP服務(wù)器或socket對(duì)象,通過(guò)將這些handle傳遞給子進(jìn)程。子進(jìn)程將會(huì)在message事件中,將該handle傳遞給Callback函數(shù),從而可以在子進(jìn)程中進(jìn)行處理。

我們看一個(gè)傳遞TCP server的例子,首先看主進(jìn)程:

const subprocess = require('child_process').fork('subprocess.js');

// 打開(kāi) server 對(duì)象,并發(fā)送該句柄。
const server = require('net').createServer();
server.on('connection', (socket) => {
 socket.end('由父進(jìn)程處理');
});
server.listen(1337, () => {
 subprocess.send('server', server);
});

再看子進(jìn)程:

process.on('message', (m, server) => {
 if (m === 'server') {
 server.on('connection', (socket) => {
 socket.end('由子進(jìn)程處理');
 });
 }
});

可以看到子進(jìn)程接收到了server handle,并且在子進(jìn)程中監(jiān)聽(tīng)connection事件。

下面我們看一個(gè)傳遞socket對(duì)象的例子:

onst { fork } = require('child_process');
const normal = fork('subprocess.js', ['normal']);
const special = fork('subprocess.js', ['special']);

// 開(kāi)啟 server,并發(fā)送 socket 給子進(jìn)程。
// 使用 `pauseOnConnect` 防止 socket 在被發(fā)送到子進(jìn)程之前被讀取。
const server = require('net').createServer({ pauseOnConnect: true });
server.on('connection', (socket) => {

 // 特殊優(yōu)先級(jí)。
 if (socket.remoteAddress === '74.125.127.100') {
 special.send('socket', socket);
 return;
 }
 // 普通優(yōu)先級(jí)。
 normal.send('socket', socket);
});
server.listen(1337);

subprocess.js的內(nèi)容:

process.on('message', (m, socket) => {
 if (m === 'socket') {
 if (socket) {
 // 檢查客戶端 socket 是否存在。
 // socket 在被發(fā)送與被子進(jìn)程接收這段時(shí)間內(nèi)可被關(guān)閉。
 socket.end(`請(qǐng)求使用 ${process.argv[2]} 優(yōu)先級(jí)處理`);
 }
 }
});

主進(jìn)程創(chuàng)建了兩個(gè)subprocess,一個(gè)處理特殊的優(yōu)先級(jí), 一個(gè)處理普通的優(yōu)先級(jí)。

異步創(chuàng)建進(jìn)程

child_process模塊有4種方式可以異步創(chuàng)建進(jìn)程,分別是child_process.spawn()、child_process.fork()、child_process.exec() 和 child_process.execFile()。

先看一個(gè)各個(gè)方法的定義:

child_process.spawn(command[, args][, options])

child_process.fork(modulePath[, args][, options])

child_process.exec(command[, options][, callback])

child_process.execFile(file[, args][, options][, callback])

其中child_process.spawn是基礎(chǔ),他會(huì)異步的生成一個(gè)新的進(jìn)程,其他的fork,exec和execFile都是基于spawn來(lái)生成的。

fork會(huì)生成新的Node.js 進(jìn)程。

exec和execFile是以新的進(jìn)程執(zhí)行新的命令,并且?guī)в衏allback。他們的區(qū)別就在于在windows的環(huán)境中,如果要執(zhí)行.bat或者.cmd文件,沒(méi)有shell終端是執(zhí)行不了的。這個(gè)時(shí)候就只能以exec來(lái)啟動(dòng)。execFile是無(wú)法執(zhí)行的。

或者也可以使用spawn。

我們看一個(gè)在windows中使用spawn和exec的例子:

// 僅在 Windows 上。
const { spawn } = require('child_process');
const bat = spawn('cmd.exe', ['/c', 'my.bat']);

bat.stdout.on('data', (data) => {
 console.log(data.toString());
});

bat.stderr.on('data', (data) => {
 console.error(data.toString());
});

bat.on('exit', (code) => {
 console.log(`子進(jìn)程退出,退出碼 $[code]`);
});
const { exec, spawn } = require('child_process');
exec('my.bat', (err, stdout, stderr) => {
 if (err) {
 console.error(err);
 return;
 }
 console.log(stdout);
});

// 文件名中包含空格的腳本:
const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true });
// 或:
exec('"my script.cmd" a b', (err, stdout, stderr) => {
 // ...
});

同步創(chuàng)建進(jìn)程

同步創(chuàng)建進(jìn)程可以使用child_process.spawnSync()、child_process.execSync() 和 child_process.execFileSync() ,同步的方法會(huì)阻塞 Node.js 事件循環(huán)、暫停任何其他代碼的執(zhí)行,直到子進(jìn)程退出。

通常對(duì)于一些腳本任務(wù)來(lái)說(shuō),使用同步創(chuàng)建進(jìn)程會(huì)比較常用。

到此這篇關(guān)于在nodejs中創(chuàng)建child process的方法的文章就介紹到這了,更多相關(guān)nodejs中創(chuàng)建child process內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 吐槽一下我所了解的Node.js

    吐槽一下我所了解的Node.js

    用了一年多 Node.js, 現(xiàn)在已經(jīng)是 Node.js 的腦殘粉了,這篇日志比較雜,算是我對(duì) Node.js 方方面面的一個(gè)集中吐槽。
    2014-10-10
  • Linux CentOS系統(tǒng)下安裝node.js與express的方法

    Linux CentOS系統(tǒng)下安裝node.js與express的方法

    這篇文章主要給大家介紹了在Linux CentOS系統(tǒng)下安裝node.js與express的方法,文中介紹的非常詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-04-04
  • 快速使用node.js進(jìn)行web開(kāi)發(fā)詳解

    快速使用node.js進(jìn)行web開(kāi)發(fā)詳解

    本篇文章主要介紹了快速使用node.js進(jìn)行web開(kāi)發(fā)詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • 關(guān)于沒(méi)有徹底清除node和npm的解決方法

    關(guān)于沒(méi)有徹底清除node和npm的解決方法

    最近因?yàn)閚pm和node的版本不匹配遇到了許多困難,比如更新npm的版本,結(jié)果它給報(bào)錯(cuò)了,查閱了好多資料,發(fā)現(xiàn)就是node和npm卸載的時(shí)候,還有殘留,所以本文給大家介紹了關(guān)于沒(méi)有徹底清除node和npm的解決方法,需要的朋友可以參考下
    2024-03-03
  • Node.js模塊封裝及使用方法

    Node.js模塊封裝及使用方法

    這篇文章主要為大家詳細(xì)介紹了Node.js模塊封裝及使用方法,感興趣的朋友可以參考一下
    2016-03-03
  • 輕松創(chuàng)建nodejs服務(wù)器(10):處理POST請(qǐng)求

    輕松創(chuàng)建nodejs服務(wù)器(10):處理POST請(qǐng)求

    這篇文章主要介紹了輕松創(chuàng)建nodejs服務(wù)器(10):處理POST請(qǐng)求,本文告訴你如何實(shí)現(xiàn)在node.js中處理POST請(qǐng)求,需要的朋友可以參考下
    2014-12-12
  • node實(shí)現(xiàn)批量上傳本地圖片轉(zhuǎn)為圖片CDN的項(xiàng)目實(shí)踐

    node實(shí)現(xiàn)批量上傳本地圖片轉(zhuǎn)為圖片CDN的項(xiàng)目實(shí)踐

    本文主要介紹了node實(shí)現(xiàn)批量上傳本地圖片轉(zhuǎn)為圖片CDN的項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • nodejs命令行參數(shù)處理模塊commander使用實(shí)例

    nodejs命令行參數(shù)處理模塊commander使用實(shí)例

    這篇文章主要介紹了nodejs命令行參數(shù)處理模塊commander使用實(shí)例,commander是一個(gè)非常高大上的令行參數(shù)處理模塊,需要的朋友可以參考下
    2014-09-09
  • 從Node.js事件觸發(fā)器到Vue自定義事件的深入講解

    從Node.js事件觸發(fā)器到Vue自定義事件的深入講解

    這篇文章主要給大家介紹了關(guān)于從Node.js事件觸發(fā)器到Vue自定義事件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Grunt針對(duì)靜態(tài)文件的壓縮,版本控制打包的實(shí)例講解

    Grunt針對(duì)靜態(tài)文件的壓縮,版本控制打包的實(shí)例講解

    下面小編就為大家?guī)?lái)一篇Grunt針對(duì)靜態(tài)文件的壓縮,版本控制打包的實(shí)例講解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09

最新評(píng)論

安图县| 金川县| 深州市| 武城县| 罗山县| 璧山县| 泸西县| 广汉市| 万源市| 得荣县| 宁阳县| 富平县| 岑溪市| 广东省| 平果县| 精河县| 隆安县| 望城县| 镶黄旗| 社旗县| 桓台县| 太康县| 嘉祥县| 合山市| 克什克腾旗| 鹤壁市| 扶沟县| 东辽县| 沽源县| 星座| 石首市| 内丘县| 东丽区| 屏边| 密云县| 革吉县| 金乡县| 日喀则市| 龙江县| 黎平县| 布拖县|