Zol*_*tan 57 javascript node.js promise bluebird
我在Node.js下使用Bluebird promise库,这太棒了!但我有一个问题:
如果你看一下Node的child_process.exec和child_process.execFile的文档,你会发现这两个函数都返回了一个ChildProcess对象.
那么推荐这种功能的方法是什么?
请注意以下工作(我得到一个Promise对象):
var Promise = require('bluebird');
var execAsync = Promise.promisify(require('child_process').exec);
var execFileAsync = Promise.promisify(require('child_process').execFile);
Run Code Online (Sandbox Code Playgroud)
但是如何才能访问原始Node.js函数的原始返回值?(在这些情况下,我需要能够访问最初返回的ChildProcess对象.)
任何建议将不胜感激!
编辑:
下面是一个使用child_process.exec函数返回值的示例代码:
var exec = require('child_process').exec;
var child = exec('node ./commands/server.js');
child.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function(data) {
console.log('stderr: ' + data);
});
child.on('close', function(code) {
console.log('closing code: ' + code);
});
Run Code Online (Sandbox Code Playgroud)
但是,如果我将使用exec函数的promisified版本(上面的execAsync),那么返回值将是一个promise,而不是ChildProcess对象.这是我正在谈论的真正问题.
Iva*_*ton 62
听起来你想从电话中回复两件事:
所以"推荐的方式来宣传这些功能"?不要.
你不在大会之外.承诺返回函数有望返回一个承诺,就是这样.你可以返回一个有两个成员的对象(ChildProcess和promise),但这只会让人感到困惑.
我建议调用unpromisified函数,并根据返回的childProcess创建一个promise.(也许把它包装成辅助函数)
这样,对于下一个阅读代码的人来说,这是非常明确的.
就像是:
var Promise = require('bluebird');
var exec = require('child_process').execFile;
function promiseFromChildProcess(child) {
return new Promise(function (resolve, reject) {
child.addListener("error", reject);
child.addListener("exit", resolve);
});
}
var child = exec('ls');
promiseFromChildProcess(child).then(function (result) {
console.log('promise complete: ' + result);
}, function (err) {
console.log('promise rejected: ' + err);
});
child.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
child.on('close', function (code) {
console.log('closing code: ' + code);
});
Run Code Online (Sandbox Code Playgroud)
use*_*021 19
从 Node v12 开始,内置函数util.promisify允许访问内置函数ChildProcess返回的对象,而该对象本Promise应由未承诺的调用返回。从文档:
返回的
ChildProcess实例Promise作为child属性附加到。
这正确且简单地满足了ChildProcess在原始问题中访问的需要,并使其他答案过时,前提是可以使用 Node v12+。
改编提问者提供的示例(和简洁风格),ChildProcess可以像这样访问:
const util = require('util');
const exec = util.promisify(require('child_process').exec);
const promise = exec('node ./commands/server.js');
const child = promise.child;
child.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function(data) {
console.log('stderr: ' + data);
});
child.on('close', function(code) {
console.log('closing code: ' + code);
});
// i.e. can then await for promisified exec call to complete
const { stdout, stderr } = await promise;
Run Code Online (Sandbox Code Playgroud)
Lac*_*mov 18
这是另一种方式:
function execPromise(command) {
return new Promise(function(resolve, reject) {
exec(command, (error, stdout, stderr) => {
if (error) {
reject(error);
return;
}
resolve(stdout.trim());
});
});
}
execPromise(command).then(function(result) {
console.log(result);
}).catch(function(e) {
console.error(e.message);
});
Run Code Online (Sandbox Code Playgroud)
或者使用async/await:
try {
var result = await execPromise(command);
} catch (e) {
console.error(e.message);
}
Run Code Online (Sandbox Code Playgroud)
shm*_*mck 18
我建议使用语言内置的标准JS Promise,而不是像Bluebird这样的附加库依赖项。
如果您使用的是Node 10+,则Node.js文档建议使用util.promisifywhich返回一个Promise<{ stdout, stderr }>对象。请参阅以下示例:
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function lsExample() {
const { stdout, stderr } = await exec('ls');
console.log('stdout:', stdout);
console.log('stderr:', stderr);
}
lsExample()
Run Code Online (Sandbox Code Playgroud)
首先从处理错误stderr。
可能没有办法很好地涵盖所有用例.但对于有限的情况,您可以这样做:
/**
* Promisified child_process.exec
*
* @param cmd
* @param opts See child_process.exec node docs
* @param {stream.Writable} opts.stdout If defined, child process stdout will be piped to it.
* @param {stream.Writable} opts.stderr If defined, child process stderr will be piped to it.
*
* @returns {Promise<{ stdout: string, stderr: stderr }>}
*/
function execp(cmd, opts) {
opts || (opts = {});
return new Promise((resolve, reject) => {
const child = exec(cmd, opts,
(err, stdout, stderr) => err ? reject(err) : resolve({
stdout: stdout,
stderr: stderr
}));
if (opts.stdout) {
child.stdout.pipe(opts.stdout);
}
if (opts.stderr) {
child.stderr.pipe(opts.stderr);
}
});
}
Run Code Online (Sandbox Code Playgroud)
这接受opts.stdout和opts.stderr参数,以便可以从子进程捕获stdio.
例如:
execp('ls ./', {
stdout: new stream.Writable({
write: (chunk, enc, next) => {
console.log(chunk.toString(enc));
next();
}
}),
stderr: new stream.Writable({
write: (chunk, enc, next) => {
console.error(chunk.toString(enc));
next();
}
})
}).then(() => console.log('done!'));
Run Code Online (Sandbox Code Playgroud)
或者干脆:
execp('ls ./', {
stdout: process.stdout,
stderr: process.stderr
}).then(() => console.log('done!'));
Run Code Online (Sandbox Code Playgroud)
只是想提一下,有一个很好的工具可以完全解决你的问题:
https://www.npmjs.com/package/core-worker
该软件包使处理流程变得更加容易.
import { process } from "CoreWorker";
import fs from "fs";
const result = await process("node Server.js", "Server is ready.").ready(1000);
const result = await process("cp path/to/file /newLocation/newFile").death();
Run Code Online (Sandbox Code Playgroud)
或结合这些功能:
import { process } from "core-worker";
const simpleChat = process("node chat.js", "Chat ready");
setTimeout(() => simpleChat.kill(), 360000); // wait an hour and close the chat
simpleChat.ready(500)
.then(console.log.bind(console, "You are now able to send messages."))
.then(::simpleChat.death)
.then(console.log.bind(console, "Chat closed"))
.catch(() => /* handle err */);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
43162 次 |
| 最近记录: |