Javascript 从gjs读取异步标准输出

Javascript 从gjs读取异步标准输出,javascript,asynchronous,gnome,gnome-shell-extensions,gjs,Javascript,Asynchronous,Gnome,Gnome Shell Extensions,Gjs,我试图从gjs运行一个命令并异步读取输出 这是我的同步代码 let [res, pid, in_fd, out_fd, err_fd] = GLib.spawn_async_with_pipes(null, ['/bin/ls'], null, 0, null); let out_reader = new Gio.DataInputStream({ base_stream: new Gio.U

我试图从gjs运行一个命令并异步读取输出

这是我的同步代码

let [res, pid, in_fd, out_fd, err_fd] = GLib.spawn_async_with_pipes(null,
                                                  ['/bin/ls'], null, 0, null);
let out_reader = new Gio.DataInputStream({
  base_stream: new Gio.UnixInputStream({fd: out_fd})
});
var out = out_reader.read_until("", null);
print(out);
这很好,但如果我尝试异步执行,它就不起作用

let [res, pid, in_fd, out_fd, err_fd]  = GLib.spawn_async_with_pipes(null,
                                                   ['/bin/ls'], null, 0, null);
let out_reader = new Gio.DataInputStream({
  base_stream: new Gio.UnixInputStream({fd: out_fd})
});
function _SocketRead(source_object, res, user_data){
  print("hi");
  let length;
  let out = out_reader.read_upto_finish(asyncResult, length);
  print("out" + out);
  print("length" + length);
}
var out = out_reader.read_upto_async("",0, 0, null, _SocketRead, "");
while(true){
   i = 0;
}

回调根本不被调用

首先谢谢你的提问,我还有一个相同的基本问题,那就是,你的第一行“我正在尝试从gjs运行一个命令并异步读取输出”,你的问题包含了我找到解决方案所需的详细信息

在示例代码中,主要问题是以下几行:

while(true){
   i = 0;
}
您正确地尝试在获得输出之前阻止程序终止,但此解决方案不起作用

Javascript是单线程的,这意味着虽然计算可以在串行交错的意义上并发运行,但不能有两个Javascript计算并行运行。没有办法显式地产生线程,问题中的忙循环一直在旋转,回调永远不会得到CPU时间

您想要的是进入一个事件循环。如果您正在开发Gnome外壳扩展,那么您已经在其中运行了,但是如果您只是在使用Gjs运行脚本,那么您需要显式地启动一个。我将使用混乱,但其他一些事件循环也可以。以下代码段构成了完整的工作解决方案

首先,让我们从导入所需的库开始:

const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Clutter = imports.gi.Clutter;
然后添加问题中的生成和文件描述符:

const [res, pid, in_fd, out_fd, err_fd] = GLib.spawn_async_with_pipes(null, ['/bin/ls'], null, 0, null);
const out_reader = new Gio.DataInputStream({
  base_stream: new Gio.UnixInputStream({fd: out_fd})
});
调用async reading函数并给它一个回调(定义如下,在这里可以使用Javascript):

然后启动事件循环:

Clutter.init(null);
Clutter.main();
回调中有几个错误,因此这里有一个固定版本,该版本在命令停止生成输出时也会终止事件循环:

function _SocketRead(source_object, res){
  const [out, length] = out_reader.read_upto_finish(res);
  if (length > 0) {
    print("out: " + out);
    print("length: " + length);
    out_reader.read_upto_async("", 0, 0, null, _SocketRead, "");
  } else {
    Clutter.main_quit();
  } 
} 
如需进一步阅读,请参阅文档中的Gjs本机绑定

function _SocketRead(source_object, res){
  const [out, length] = out_reader.read_upto_finish(res);
  if (length > 0) {
    print("out: " + out);
    print("length: " + length);
    out_reader.read_upto_async("", 0, 0, null, _SocketRead, "");
  } else {
    Clutter.main_quit();
  } 
}