child_process在Node.js中的表现如何

时间:2019-04-08 18:50:10

标签: node.js child-process

我有一个有效的Node.js代码,但是child_process库的行为很奇怪,我只是想知道该库是如何工作的。

我的代码尝试从S3下载SSL证书,然后使用child_process库基于现有文件创建两个新文件。

const AWS = require('aws-sdk');
const fs = require('fs');
const child_process = require("child_process");
const exec = require('child_process').exec; 

var s3 = new AWS.S3();

var filePath = '../Desktop/Certs/'
var bucketName = 'neb.certificates' //replace example bucket with your s3 bucket name

var params = {
    Bucket: bucketName, 
    Prefix: 'dev/jenkins.secure.care/',
  };

  s3.listObjectsV2(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else {
        // console.log(data.Contents)
        var len = data.Contents.length

        for(var i=0; i<len; i++){
            var key = data.Contents[i]["Key"]

            var newPath = filePath.concat(key.substring(31))

            const downloadFile = (newPath, bucketName, key) => {

                //construct getParam
                var getParams = {
                    Bucket: bucketName,
                    Key: key
                };

                s3.getObject(getParams, (err, data) => {
                    if (err) console.error(err)
                    fs.writeFileSync(newPath, data.Body.toString())
                    // console.log(`${newPath} has been created!`)
                })
            }

            downloadFile(newPath, bucketName, key)
        }
    }
  });

  exec('mv  ../Desktop/Certs/cert.pem ../Desktop/Certs/jenkins.crt', (err, stdout, stderr) => {  
    if (err) {  
      console.error(err);  
      return;  
    }  
    console.log(stdout);  
  }); 

  exec('mv ../Desktop/Certs/privkey.pem ../Desktop/Certs/jenkins.key', (err, stdout, stderr) => {  
    if (err) {  
      console.error(err);  
      return;  
    }  
    console.log(stdout);  
  }); 

因此,当我第一次运行代码时,它仅将证书从S3下载到本地文件夹,而没有创建其他2个文件。然后,我必须第二次运行它来创建其他文件。

但是,我只想运行一次,它具有我期望的一切。

我添加了一个代码,该代码可以休眠5秒钟,然后创建其他文件,但这并不能解决我的问题,这意味着我仍然需要运行两次代码才能获得所有内容。

child_process.execSync("sleep 5");

请帮助

1 个答案:

答案 0 :(得分:1)

这里的问题似乎是代码的异步执行。在此示例中,正在发生的事情:

  1. 运行s3.listObjectsV2()完成后,触发回调(但不是现在,将来是
  2. 首先运行exec(),然后完成 ,触发回调(但不是现在,将来
  3. 运行exec(),然后第二次完成{em> ,触发回调(但不是现在,将来是

这三个步骤立即被一一解雇。而且每个都有自己的回调,将来会触发 。好的,但是未来是什么时候? -完全是!你不知道在您的情况下,exec()中的这两个回调可能在s3的回调之前被触发,这就是为什么它不起作用的原因。

这里的解决方案是确保在exec()之后触发这些s3.listObjects。因此,您有两种选择:首先是在s3中做出承诺,例如:s3.listObjectsV2(params).promise()await,然后在.then((data) => {})中拥有{{ 1}},在data中,您拥有.catch((error) => {})。或者,您可以简单地将这些error放在exec()调用的回调中。


根据解决方案2(来自注释),您的代码应如下所示:

s3