Прежде всего, спасибо за этот вопрос, у меня также был тот же основной вопрос, то есть ваша начальная строка «Я пытаюсь запустить команду из gjs и читать асинхронный вывод» и ваш квест у Иона были детали, которые мне нужны, чтобы найти решение!
В вашем примере коде, главная проблема заключается в этих строках:
while(true){
i = 0;
}
Вы правильно пытаетесь сохранить программу от завершения, прежде чем получить результат, но это решение не работает.
Javascript является однопоточным, что означает, что, хотя вычисления могут выполняться одновременно в последовательном чередовании, не может быть двух параллельных вычислений Javascript. Невозможно явно передать поток, и цикл занятости в вопросе просто продолжает вращаться, и обратный вызов никогда не получает процессорное время.
Вместо этого вы должны ввести цикл событий. Если вы разрабатываете расширение 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 hoisting):
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();
}
}
Для Дальнейшее чтение содержит документы привязки Gjs на уровне https://people.gnome.org/~gcampagna/docs.