从其他文件执行异步代码时,Node.js 和 node-gtk 问题

jcu*_*bic 5 javascript gtk node.js

我有一个非常具体的问题,我不确定可能是在应用程序运行时完成的 node.js 进程的某种垃圾收集或其他问题。

所以我有用 JavaScript 编写的 Scheme 实现,我正在尝试运行 Scheme 代码,它是带有标签的应用程序的 node-gtk 基本示例。问题是标签没有插入到窗口中,我从屏幕下方看到了带有背景的破碎窗口,当我移动窗口时会留下来。

在此处输入图片说明

我有具有此s​​hebang的node.js可执行文件:

 #!/usr/bin/env node
Run Code Online (Sandbox Code Playgroud)

我的方案代码是来自 node-gtk 的1-1演示,但在方案中,将其作为shebang:

#!/home/kuba/projects/jcubic/lips/bin/lips.js
Run Code Online (Sandbox Code Playgroud)

临时本地实例,因为我正在开发下一个版本。它还适用于:

#!/usr/bin/env lips
Run Code Online (Sandbox Code Playgroud)

这是我的 REPL 和文件执行的部分代码:

if (options._.length === 1) {
    fs.readFile(options._[0], function(err, data) {
        var e = env.inherit('name');
        if (err) {
            console.error(err);
        } else {
            boostrap(e).then(function() {
                return run(data.toString().replace(/^#!.*\n/, ''), e);
            });
            console.log('HELLO');
        }
    });
} else if (options.h) {
    var name = process.argv[1];
    console.log(format('%s\nusage:\n%s [-h]|[-c <code>]|<filename>\n\n\t-h this help message\n\t-c execute' +
                       ' code\n\nif called without arguments it will run REPL and if called with one argument' +
                       '\nit will treat it as filename and execute it.', intro, name));
} else {
    if (process.stdin.isTTY) {
        console.log(banner);
    }
    var prompt = 'lips> ';
    var continuePrompt = '... ';
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
        prompt: prompt,
        terminal: !!process.stdin.isTTY
    });
    if (process.stdin.isTTY) {
        rl.prompt();
    }
    var code = '';
    var multiline = false;
    var resolve;
    var e = env.inherit('name', {
        stdin: InputPort(function() {
            return new Promise(function(resolve) {
                rl.question('', resolve);
            });
        }),
        stdout: OutputPort(function(x) {
            //rl.write(this.get('repr')(x));
            console.log(this.get('repr')(x));
        })
    });
    boostrap(e).then(function() {
        rl.on('line', function(line) {
            code += line + '\n';
            if (balanced_parenthesis(code)) {
                rl.pause();
                run(code, e).then(function(result) {
                    if (process.stdin.isTTY) {
                        print(result);
                        if (multiline) {
                            rl.setPrompt(prompt);
                        }
                        rl.prompt();
                    }
                    rl.resume();
                }).catch(function() {
                    if (process.stdin.isTTY) {
                        if (multiline) {
                            rl.setPrompt(prompt);
                        }
                        rl.prompt();
                    }
                });
                code = '';
            } else {
                multiline = true;
                var i = indent(code, 2, prompt.length - continuePrompt.length);
                rl.setPrompt(continuePrompt);
                rl.prompt();
                rl.write(new Array(i + 1).join(' '));
            }
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

如果我首先执行 if 语句,则 node-gtk 应用程序会像在经过验证的屏幕上一样损坏,但是如果我使用 readline 作为 REPL 运行并复制粘贴相同的代码,则它可以工作。如果我运行这个也一样:

../lips/bin/lips.js < ./run.scm
Run Code Online (Sandbox Code Playgroud)

但是从repl的多行案例中得到了额外的“...”。执行此方案脚本的正确方法是什么?

我还在 node-gtk repo https://github.com/romgrk/node-gtk/issues/170 中创建了一个问题

我也尝试过使用承诺:

// this is the object that hold references
// while the scheme code is running
let e = env.inherit('name'); 
fs.promises.readFile(options._[0]).then(function(data) {
    return boostrap(e).then(function() {
        return run(data.toString().replace(/^#!.*\n/, ''), e);
    });
}).catch(err => {
    console.error(err);
});
Run Code Online (Sandbox Code Playgroud)

但问题仍然存在。

bootstrap 函数只加载外部文件,并运行只是将代码评估为字符串,在 Scheme 代码中创建的变量保存在环境中(这是 中的普通对象e.env)。

工作黑客

如果我添加此代码:

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
Run Code Online (Sandbox Code Playgroud)

在我的代码工作之前,它有点像黑客。为什么这有效,有没有更好的方法?我想了解为什么会发生这种情况以及这是如何工作的。