【问题标题】:nodejs wait for exec in functionnodejs在函数中等待exec
【发布时间】:2016-12-08 10:23:05
【问题描述】:

我喜欢将 nodejs 中的 exec 集成到一个自定义函数中,以处理这个函数中的所有错误。

const exec = require('child_process').exec;

function os_func() {
    this.execCommand = function(cmd) {
        var ret;
        exec(cmd, (error, stdout, stderr) => {
            if (error) {
                console.error(`exec error: ${error}`);
                return;
            }
            ret = stdout;
        });
        return ret;
    }
}
var os = new os_func();

此函数返回未定义,因为值返回时 exec 尚未完成。 我该如何解决?我可以强制函数等待执行吗?

【问题讨论】:

标签: javascript node.js function exec


【解决方案1】:

由于命令是异步执行的,一旦命令执行完毕,您将需要使用callback 来处理返回值:

const exec = require('child_process').exec;

function os_func() {
    this.execCommand = function(cmd, callback) {
        exec(cmd, (error, stdout, stderr) => {
            if (error) {
                console.error(`exec error: ${error}`);
                return;
            }

            callback(stdout);
        });
    }
}
var os = new os_func();

os.execCommand('SomeCommand', function (returnvalue) {
    // Here you can get the return value
});

【讨论】:

    【解决方案2】:

    你可以使用 promise 为:

    const exec = require('child_process').exec;
    
    function os_func() {
        this.execCommand = function (cmd) {
            return new Promise((resolve, reject)=> {
               exec(cmd, (error, stdout, stderr) => {
                 if (error) {
                    reject(error);
                    return;
                }
                resolve(stdout)
               });
           })
       }
    }
    var os = new os_func();
    
    os.execCommand('pwd').then(res=> {
        console.log("os >>>", res);
    }).catch(err=> {
        console.log("os >>>", err);
    })
    

    【讨论】:

      【解决方案3】:

      exec 将以异步方式处理它,因此您应该收到回调或返回承诺。

      为了使其同步,您可以做的一件事是改用 execSync

      https://nodejs.org/api/child_process.html#child_process_child_process_execsync_command_options

      child_process.execSync() 方法通常与 child_process.exec() 除了该方法不会 返回直到子进程完全关闭。当超时 遇到并发送了killSignal,该方法不会返回,直到 该过程已完全退出。注意如果子进程 拦截并处理 SIGTERM 信号并且不退出,父级 进程会一直等到子进程退出。

      【讨论】:

        【解决方案4】:

        另一个使用 ES6 模块的解决方案:

        import fs from "node:fs";
        import {exec} from "node:child_process";
        import util from "node:util";
        
        // promisify exec
        const execPromise = util.promisify(exec);
        
        try {
          // wait for exec to complete
          const {stdout, stderr} = await execPromise("ls -l");
        } catch (error) {
          console.log(error);
        }
        

        【讨论】:

          【解决方案5】:

          你可以通过回调来做到这一点。也许你可以尝试这样的事情:

          function os_func() {
          this.execCommand = function(cmd, myCallback) {
              var ret;
              exec(cmd, (error, stdout, stderr) => {
                  if (error) {
                      console.error(`exec error: ${error}`);
                      return;
                  }
                  ret = stdout;
                  myCallback(ret);
          
              });
          }
          
          
          function myCallback(ret){
                // TODO: your stuff with return value...
          }
          

          【讨论】:

            【解决方案6】:

            添加对我有用的东西,因为以上都没有成功!

            const { exec } = require("child_process");
            const util  = require("util");
            const execPromise = util.promisify(exec);
            
            function parentFunction() {
            ...
              // Trigger 'exec', then a-wait for it to finish
              await execWrapper('<your-command-here>');
            ...
            }
            
            ...
            async function execWrapper(cmd) {
              const { stdout, stderr } = await execPromise(cmd);
              if (stdout) {
                console.log(`stderr: ${stdout}`);
              }
              if (stderr) {
                console.log(`stderr: ${stderr}`);
              }
            }
            

            注意:这不是您的示例,而只是一个通用示例;对我来说 - cmd 是一个 Docker build 命令。如果需要,您可以让execWrapper 返回stdout

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-06-21
              • 2023-01-31
              • 2016-10-29
              • 2020-09-23
              • 1970-01-01
              • 2021-02-25
              • 2017-08-19
              相关资源
              最近更新 更多