2017-07-26 72 views
0

我试图在nodejs内执行几个python脚本。代码如下所示。我想要做的是在for循环内逐个执行不同的python脚本。并在一个脚本结束后立即将json响应发送给客户端。使用python-shell发送多个来自nodejs的响应

var PythonShell = require('python-shell'); 
var express = require('express'), app = express(); 

app.get('/', function (req, res) { 
    res.setHeader('Content-Type', 'text/html'); 

    pl_list=["test", "test2"] 
    for (var i=0; i<= pl_list.length-1; i++) { 
    output=""; 

var pyshell = new PythonShell('./'+pl_list[i]+'.py') 
pyshell.on('message', function (message) 

{console.log(message);output+=message;}); 
    pyshell.end(function (err) { 
     if (err){ 
      console.log('error occured ---- '+err); 

     } 
     else{ 
      console.log('update finished'); 
      res.write(JSON.stringify({"finsihed":true, "product_line":pl_list[i]})); 
     } 
    }); 

    } 
    //res.end() 
}); 

app.listen(5000, function() { 
    console.log('The web server is running. Please open http://localhost:5000/ in your browser.'); 
}); 

不幸的是我得到了响应,{"finsihed":true}实际输出必须 {"finsihed":true, "product_line":"test"}{"finsihed":true, "product_line":"test2"} 有谁能够告诉我,我在做什么错在这里。提前致谢!

回答

1

你的Python脚本的执行是异步的,所以当你写这一行的响应到客户端,i的值改为:

res.write(JSON.stringify({"finsihed":true, "product_line":pl_list[i]}) 

只显示我用的console.log前值上面的行,你会看到我等于2次(由于你的for循环的增量)。并且因为pl_list[i]未定义,所以JSON对象的序列化将删除属性“product_line”。

如果您想“保存”我的价值,您必须了解closure是什么。

此代码应工作:

var PythonShell = require('python-shell'); 
var express = require('express'), 
    app = express(); 

app.get('/', function (req, res) { 
    res.setHeader('Content-Type', 'text/html'); 

    var nbFinishedScripts = 0; 

    pl_list = ["test", "test2"] 
    for (var i = 0; i <= pl_list.length - 1; i++) { 
     output = ""; 

     var pyshell = new PythonShell('./' + pl_list[i] + '.py') 
     pyshell.on('message', function (message) 

      { 
       console.log(message); 
       output += message; 
      }); 

     // closure 
     (function (i) { 
      return function() { 
       pyshell.end(function (err) { 
        if (err) { 
         console.log('error occured ---- ' + err); 

        } else { 
         console.log('update finished'); 
         res.write(JSON.stringify({ 
          "finsihed": true, 
          "product_line": pl_list[i] 
         })); 
        } 

        nbFinishedScripts++; 

        // end the reponse when the number of finished scripts is equal to the number of scripts 
        if (nbFinishedScripts === pl_list.length) { 
         res.end(); 
        } 
       }); 
      }; 
     })(i)(); // immediately invoke the function 
    } 
}); 

app.listen(5000, function() { 
    console.log('The web server is running. Please open http://localhost:5000/ in your browser.'); 
}); 

编辑代码:

var PythonShell = require('python-shell'); 
var express = require('express'), 
    app = express(); 

var executePythonScript = function (script) { 
    return new Promise(function (resolve, reject) { 
     var pyshell = new PythonShell('./' + script + '.py'); 
     pyshell.end(function (err) { 
      if (err) { 
       reject(err); 
      } else { 
       resolve(script); 
      } 
     }); 
    }); 
}; 

app.get('/', function (req, res) { 
    res.setHeader('Content-Type', 'text/html'); 

    var pl_list = ["test", "test2"]; 

    Promise 
     .all(pl_list.map(executePythonScript)) 
     .then(function (scripts) { 
      scripts.forEach(function (script) { 
       res.write(JSON.stringify({ 
        finsihed: true, 
        product_line: script 
       })); 
      }); 

      res.end(); 
     }) 
     .catch(function (err) { 
      res.end(); 
     }); 
}); 

app.listen(5000, function() { 
    console.log('The web server is running. Please open http://localhost:5000/ in your browser.'); 
}); 
+0

感谢您的帮助,但是当我执行上面的代码的响应'{ “finsihed”:真实的,“product_line “:”test2“} {”finsihed“:true,”product_line“:”test“}'而不是'{”finsihed“:true,”product_line“:”test“} {”finsihed“:true,”product_line“ :“test2”}' –

+0

响应必须与'pl_list'中的值相同。 –

+0

如果您希望您的响应始终处于相同顺序,则必须使用s ome工具可以很好地处理异步操作。我编辑我的代码并选择使用承诺。告诉我它是否适合你。 –

相关问题