2

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;
}

コールバックはまったく呼び出されません

4

1 に答える 1

4

まず、質問に感謝します。同じ根本的な質問もありました。つまり、最初の行「gjs からコマンドを実行し、出力を非同期で読み取ろうとしています」であり、質問には、解決!

あなたのコード例では、主な問題は次の行です。

while(true){
   i = 0;
}

出力を取得する前にプログラムが終了しないように正しく試みていますが、この解決策は機能しません。

Javascript はシングル スレッドです。つまり、計算はシリアル インターリーブの意味で同時に実行できますが、2 つの Javascript 計算を並行して実行することはできません。スレッドを明示的に生成する方法はなく、問題のビジー ループは回転し続け、コールバックは CPU 時間を取得しません。

代わりに、イベント ループに入る必要があります。Gnome Shell 拡張機能を開発している場合は、既に実行されていますが、Gjs でスクリプトを実行しているだけの場合は、明示的に開始する必要があります。ここでは Clutter を使用しますが、他のイベント ループでも同様に機能します。次のコード セグメントは、完全で実用的なソリューションを構成します。

まず、必要なライブラリをインポートすることから始めましょう。

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})
});

非同期の読み取り関数を呼び出して、コールバックを渡します (以下で定義、Javascript ホイストのおかげでここで使用可能):

out_reader.read_upto_async("", 0, 0, null, _SocketRead, "");

そして、イベント ループを開始します。

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();
  } 
} 

さらに読むには、 https: //gjs-docs.gnome.org/ に Gjs ネイティブ バインディング ドキュメントがあります。

于 2015-11-29T13:54:14.783 に答える