Phi*_*els 7 stdout task-parallel-library node.js async-await edge.js
我正在开发一个C#程序,它目前通过Process.Start()运行Node.我从这个子进程捕获stdout和stderr并根据我自己的原因重定向它.我正在寻找通过调用Edge.js替换Node.exe的调用.为了能够做到这一点,我必须能够从Edge中运行的Javascript中可靠地捕获stdout和stderr,并将消息返回到我的C#应用程序中.
我将描述这种方法的完整性,以防任何人推荐:)
如果Edge进程终止,通过简单地声明一个msgs数组并覆盖process.stdout.write以及process.stderr.write在该数组上累积消息的新函数来处理这个问题是相当容易的,然后在最后,只返回msgs数组.例:
var msgs = [];
process.stdout.write = function (string) {
msgs.push({ stream: 'o', message : string });
};
process.stderr.write = function (string) {
msgs.push({ stream: 'e', message: string });
};
// Return to caller.
var result = { messages: msgs; ...other stuff... };
callback(null, result);
Run Code Online (Sandbox Code Playgroud)
显然,这仅在Edge代码终止时有效,并且在最坏的情况下msgs可能会变大.但是,它可能表现良好,因为只需要一次编组调用即可获得所有消息.
这有点难以解释.我们使用从C#发送的委托来"挂钩"stdout和stderr,而不是累积消息.在C#中,我们创建了一个将传递给Edge的对象,该对象具有一个名为的属性stdoutHook:
dynamic payload = new ExpandoObject();
payload.stdoutHook = GetStdoutHook();
public Func<object, Task<object>> GetStdoutHook()
{
Func<object, Task<object>> hook = (message) =>
{
TheLogger.LogMessage((message as string).Trim());
return Task.FromResult<object>(null);
};
return hook;
}
Run Code Online (Sandbox Code Playgroud)
我可以真正逃脱一个动作,但Edge似乎需要Func<object, Task<object>>,否则它不会代理该功能.然后,在Javascript中,我们可以检测到该函数并像这样使用它:
var func = Edge.Func(@"
return function(payload, callback) {
if (typeof (payload.stdoutHook) === 'function') {
process.stdout.write = payload.stdoutHook;
}
// do lots of stuff while stdout and stderr are hooked...
var what = require('whatever');
what.futz();
// terminate.
callback(null, result);
}");
dynamic result = func(payload).Result;
Run Code Online (Sandbox Code Playgroud)
Q1.这两种技术似乎都有效,但有没有更好的方法可以做到这一点,也许是我错过了Edge内置的内容?这两种解决方案都具有侵入性 - 它们需要一些填充码来包装要在Edge中完成的实际工作.这不是世界末日,但如果有一种非侵入性方法会更好.
Q2.在方法2中,我必须在这里返回任务
return Task.FromResult<object>(null);
Run Code Online (Sandbox Code Playgroud)
返回已完成的"空任务"感觉不对.但还有另一种写作方式吗?
Q3.在挂钩stdout和stderr时,我是否需要在Javascript代码中更严格?我注意到在double-edge.js中有这个代码,坦率地说我不确定这里发生了什么,但它比我粗略覆盖process.stdout.write更复杂:-)
// Fix #176 for GUI applications on Windows
try {
var stdout = process.stdout;
}
catch (e) {
// This is a Windows GUI application without stdout and stderr defined.
// Define process.stdout and process.stderr so that all output is discarded.
(function () {
var stream = require('stream');
var NullStream = function (o) {
stream.Writable.call(this);
this._write = function (c, e, cb) { cb && cb(); };
}
require('util').inherits(NullStream, stream.Writable);
var nullStream = new NullStream();
process.__defineGetter__('stdout', function () { return nullStream; });
process.__defineGetter__('stderr', function () { return nullStream; });
})();
}
Run Code Online (Sandbox Code Playgroud)
问题 1:Edge 中没有任何内置功能可以在从 CLR 调用 Node 时自动捕获 Node.js 代码的 stdout 或 stderr。在某些时候,我想到编写 Edge 的扩展,使跨 CLR/V8 边界的流编组变得容易。从本质上讲,它与方法 2 非常相似。它可以作为 Edge 之上的独立模块来完成。
Q2:在这种情况下返回已完成的任务是非常合适的。您的函数已捕获 Node.js 输出并对其进行处理,并且实际上在这个意义上已“完成”。返回一个以 Null 完成的任务实际上在道德上等同于从一个 Action 中返回。
Q3:您指向的代码仅与 Windows GUI 应用程序相关,与控制台应用程序无关。如果您正在编写控制台应用程序,则只需write在传递给 Edge.js 的 Node.js 代码级别进行覆盖就足够了。write请注意, in Node的签名允许传入可选的编码参数。您似乎在方法 1 和方法 2 中都忽略了它。特别是在方法 2 中,我建议将 C# 回调的 JavaScript 代理包装到 JavaScript 函数中,该函数在将参数分配给process.stdout.write. 否则,Edge.js 代码可能会假设encoding传递给write调用的参数是遵循 Edge.js 调用约定的回调函数。
| 归档时间: |
|
| 查看次数: |
1250 次 |
| 最近记录: |