NodeJS 是否可以等待shell命令完全执行,然后在命令执行后返回一些内容?

8ehkhllq  于 2023-01-25  发布在  Node.js
关注(0)|答案(1)|浏览(143)

我试图使一个函数,返回1后,从终端的命令是完全执行。
你知道怎么做吗?
这是我的代码:

const speed = async () => {
try {
    exec(`speedtest`, (error, stdout, stderr) => {
        if (error) {
            // console.log(`error: ${error.message}`);
            return;
        }
        if (stderr) {
            console.log(`stderr: ${stderr}`);
            return;
        }
        console.log(`stdout: ${stdout}`);
    });
    console.log(stdout);
} catch (error) {
    console.log('error')
}

知道speedtest命令需要一些时间来打印整个输出,我想只有在命令完全执行的情况下才继续其他代码行。

ztyzrc3y

ztyzrc3y1#

您可以使用Promises来实现这一点:

const { exec } = require('child_process');

const speed = () => new Promise((resolve, reject) => {
  try {
      exec(`speedtest`, (error, stdout, stderr) => {
          if (error) {
            reject(error);
          } else if (stderr) {
            reject(stderr);
          } else {
            const downloadSpeed = stdout.match(/Download:\s+(\d+(\.\d+)?)/i);
            const uploadSpeed = stdout.match(/Upload:\s+(\d+(\.\d+)?)/i);
            const speed = {
              download: downloadSpeed? Number(downloadSpeed[1]) : null,
              upload: uploadSpeed? Number(uploadSpeed[1]) : null,
            }
            resolve(speed);
          }
          
      });
  } catch (error) {
      reject(error)
  }
});

speed()
  .then(speed => console.log('got resolve:', speed))
  .catch(error => console.log('got reject:', error));

承诺将在stdout中的某些内容出现后解决。如果您想等待特殊的内容,可以使用regular expressions并添加timeout arg:

const {
  exec
} = require('child_process');

const speed = (timeout = 60000) => new Promise((resolve, reject) => {
  try {

    const searchingString = 'Result URL:';
    let fullOutput = '';
    let finished = false;

    setTimeout(() => {
      if (finished) return;
      reject(new Error('Timeout'));
    }, timeout);

    exec(`speedtest`, (error, stdout, stderr) => {
      if (error) {
        reject(error);
      } else if (stderr) {
        reject(stderr);
      } else {
        fullOutput += stdout;
        if (fullOutput.indexOf(searchingString) === -1) {
          return;
        }
        finished = true;
        const downloadSpeed = fullOutput.match(/Download:\s+(\d+(\.\d+)?)/i);
        const uploadSpeed = fullOutput.match(/Upload:\s+(\d+(\.\d+)?)/i);
        const speed = {
          download: downloadSpeed ? Number(downloadSpeed[1]) : null,
          upload: uploadSpeed ? Number(uploadSpeed[1]) : null,
        }
        resolve(speed);
      }

    });
  } catch (error) {
    reject(error)
  }
});

speed()
  .then(speed => console.log('got resolve:', speed))
  .catch(error => console.log('got reject:', error));

另一种方法是在子进程上使用listeners

const {
  exec
} = require('child_process');

const speed = (timeout = 60000) => new Promise((resolve, reject) => {
  try {

    let fullOutput = '';

    let timer = setTimeout(() => {
      if (finished) return;
      reject(new Error('Timeout'));
    }, timeout);

    const child = exec(`speedtest`, (error, stdout, stderr) => {
      if (error) {
        reject(error);
      } else if (stderr) {
        reject(stderr);
      } else {
        fullOutput += stdout;
      }
    });

    child.on('close', () => {
      clearTimeout(timer);
      const downloadSpeed = fullOutput.match(/Download:\s+(\d+(\.\d+)?)/i);
      const uploadSpeed = fullOutput.match(/Upload:\s+(\d+(\.\d+)?)/i);
      const speed = {
        download: downloadSpeed ? Number(downloadSpeed[1]) : null,
        upload: uploadSpeed ? Number(uploadSpeed[1]) : null,
      }
      resolve(speed);
    });
    child.on('error', reject);
  } catch (error) {
    reject(error)
  }
});

speed()
  .then(speed => console.log('got resolve:', speed))
  .catch(error => console.log('got reject:', error));

相关问题