提问者:小点点

在Javascript中将派生进程中的数据保存到变量中


保存派生python进程的结果时遇到问题。将数据转换为json后,在调用spawn进程之前,我将数据推送到函数中定义的数组中,但该数组始终返回未定义的数据。我可以安慰你。正确记录并显示数据,但函数返回的数组未定义。如有任何意见,将不胜感激。提前谢谢。

function sonar_projects(){
    const projects = [];
    let obj;
    let str = '';
    const projects_py = spawn('python', ['sonar.py', 'projects']);
    let test = projects_py.stdout.on('data', function(data){
        let projects = [];
        let json = Buffer.from(data).toString()
        str += json
        let json2 = json.replace(/'/g, '"')
        obj = JSON.parse(json2)
        console.log(json2)
        for(var dat in obj){
            var project = new all_sonar_projects(obj[dat].key, obj[dat].name, obj[dat].qualifier, obj[dat].visibility, obj[dat].lastAnalysisDate);
            projects.push(project); 
        }   
        for (var i= 0; i < projects.length; i++){
             console.log(projects[i].key + ' ' + projects[i].name + '  ' + projects[i].qualifier + '  ' + projects[i].visibility + '  ' + projects[i].lastAnalysisDate)
        }
        console.log(projects)
        return projects;
    });  
}

共1个答案

匿名用户

首先,通过查阅NodeJS文档,我们有

  1. 子进程
  2. [子进程.spawn(命令,参数][,选项])
  3. 子进程类
  4. 流可读事件“数据”

即使projects_py.stdout.on(event_name,回调)接受回调,它也会返回类EventEmitter的对象,其中注册了事件(在本例中,stdout具有它的方法on调用),或元素(名为ChildProcessprojects_py)。

这是因为每次发生“data”事件时都会调用回调函数。因此,如果事件的赋值返回的与回调函数相同,那么它只会返回一次,然后“data”事件的下一次发生都会由函数处理,但不会执行。

在这种情况下,我们需要一种方法来收集和编译projects_py.stdout.on(data,回调)事件完成后的数据。你已经有了收集部分。现在看看另一个:

在创建on“data”事件之前,我们promise封装流程:

    // A promise says "we promise" to have something in the future,
    //  but it can end not happening
    var promise = new Promise((resolve, reject) => {
        // First of all, we collect only the string data
        //  as things can come in parts
        projects_py.stdout.on('data', function(data){
            let json = Buffer.from(data).toString()
            str += json
        });
        
        // When the stream data is all read,
        //  we say we get what "we promised", and give it to "be resolved"
        projects_py.stdout.on("end", () => resolve(str));
        
        // When something bad occurs,
        //  we say what went wrong
        projects_py.stdout.on("error", e => reject(e));
        
    // With every data collected,
    //  we parse it (it's most your code now)
    }).then(str => {
        let json2 = str.replace(/'/g, '"')
        // I changed obj to arr 'cause it seems to be an array
        let arr = JSON.parse(json2)
        //console.log(json2)
        
        const projects = []
        // With for-of, it's easier to get elements of
        //  an object / an array / any iterable
        for(var dat of arr){
            var project = new all_sonar_projects(
                dat.key, dat.name, dat.qualifier,
                dat.visibility, dat.lastAnalysisDate
            );
            projects.push(project); 
        }
        
        // Template strings `a${variable or expression}-/b`
        //  are easier to compile things into a big string, yet still fast
        for(var i = 0; i < projects.length; i++)
            console.log(
                `${projects[i].key} ${projects[i].name} ` +
                `${projects[i].qualifier}  ${projects[i].visibility} ` +
                projects[i].lastAnalysisDate
            )
        console.log(projects)
        
        // Your projects array, now full of data
        return projects;
    // Finally, we catch any error that might have happened,
    //  and show it on the console
    }).catch(e => console.error(e));
}

现在,如果您想对项目阵列执行任何操作,有两个主要选项:

// Your function
function sonar_projects(){
    // The new promise
    var promise = ...
    
    // As the working to get the projects array
    //  is already all set up, you just use it, but in an inner scope
    promise.then(projects => {
        ...
    });
}

此外,您可以只返回promise变量,并用它在sonar_projects之外执行promise的事情(然后使用/cat和回调)。

// First of all, you need to convert your function into an async one:
async function sonar_projects(){
    // As before, we get the promise
    var promise = ...
    
    // We tell the function to 'wait' for it's data
    var projects = await promise;
    
    // Do whatever you would do with the projects array
    ...
}