如何使用 javascript async/await 执行 shell 脚本

问题描述 投票:0回答:4

所以我有一个服务器监听 RabbitMQ 请求:

        console.log(' [*] Waiting for messages in %s. To exit press CTRL+C', q);
        channel.consume(q, async function reply(msg) {
            const mongodbUserId = msg.content.toString();
            console.log(' [x] Received %s', mongodbUserId);

            await exec('./new_user_run_athena.sh ' + mongodbUserId, function(
                error,
                stdout,
                stderr
            ) {
                console.log('Running Athena...');
                console.log('stdout: ' + stdout);
                console.log('stderr: ' + stderr);
                if (error !== null) {
                    console.log('exec error: ' + error);
                }
            });

            console.log(
                ' Finished running Athena for mongodbUserId=%s',
                mongodbUserId
            );

            channel.sendToQueue(
                msg.properties.replyTo,
                new Buffer(mongodbUserId),
                { correlationId: msg.properties.correlationId }
            );

            channel.ack(msg);
        });

问题是执行 shell 脚本

new_user_run_athena.sh
时的等待调用发生在我打印出
Finished running Athena for mongodbUserId
之后。您可以在控制台日志中看到它发生:

 [*] Waiting for messages in run_athena_for_new_user_queue. To exit press CTRL+C
 [x] Received 5aa96f36ed4f68154f3f2143
 Finished running Athena for mongodbUserId=5aa96f36ed4f68154f3f2143
Running Athena...
stdout: 
stderr:

是否可以使用异步等待语法来执行 shell 脚本?

javascript shell async-await
4个回答
2
投票

由于

exec
看起来需要回调,因此您可以使用它将其包装到承诺中。然后您可以等待该承诺,而不是直接等待
exec
调用。因此,对于您的示例,类似于:

// Await a new promise:
await new Promise((resolve, reject) => {
    exec('./new_user_run_athena.sh ' + mongodbUserId, function(
        error,
        stdout,
        stderr
    ) {
        console.log('Running Athena...');
        console.log('stdout: ' + stdout);
        console.log('stderr: ' + stderr);
        if (error !== null) {
            console.log('exec error: ' + error);
            // Reject if there is an error:
            return reject(error);
        }

        // Otherwise resolve the promise:
        resolve();
    });
});

2
投票

请参阅 MDN 文档了解

await

await 运算符用于等待 Promise。它只能在异步函数中使用。

exec
函数不会返回 Promise,因此您不能等待它。

您可以编写一个函数

exec
包装在 Promise 中并返回该 Promise。


1
投票

exec 包裹在一个承诺中。这是一个打字稿示例:

import { exec as childProcessExec } from 'child_process'

const exec = async (command: string): Promise<string> => {
  return new Promise((resolve, reject) => {
    childProcessExec(command, (error, stdout, stderr) => {
      if (error !== null) reject(error)
      if (stderr !== '') reject(stderr)
      else resolve(stdout)
    })
  })
}

用途:

const commandOutput = await exec('echo Hey there!')
console.log(commandOutput)

0
投票

根据其他示例,我想出了一个返回对象的类型化异步执行调用:

/**
 * Adds typed await and async support 
 * @param command string
 * @returns Promise<{error:ExecException, standardError:string, standardOut:string}
 */
async callProcess(command:string): Promise<{error:ExecException, standardError:string, standardOut:string}> {
  
  return new Promise((resolve, reject) => {
    childProcessExec(command, (error: ExecException, standardOut: string, standardError: string) => {
      var result = {error, standardError, standardOut};

      if (error !== null) {
        reject(result);
      }
      if (standardError !== '') {
        reject(result);
      }
      else {
        resolve(result);
      }
    })
  })
}

你这样称呼它:

try {
   var callResult = await this.callProcess(execCommand);

   if (callResult.standardOut) {

   }
}
catch(error) {

   if (error.standardError) {

   }
   else if (error.error) {
  
   }
   else {

   }
}

返回字符串的示例:

/**
 * Adds typed await and async support. 
 * In a try block returns standard out and error in catch block.  
 * @param command string
 * @returns Promise<string>
 */
async callProcess(command:string): Promise<string> {
  
  return new Promise((resolve, reject) => {
    childProcessExec(command, (error: ExecException, standardOut: string, standardError: string) => {

      if (error !== null) {
        reject(error);
      }
      if (standardError !== '') {
        reject(standardError);
      }
      else {
        resolve(standardOut);
      }
    })
  })
}

尚未经过全面测试,因此请添加任何更正。

© www.soinside.com 2019 - 2024. All rights reserved.