2017-07-26 94 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工具可以很好地處理異步操作。我編輯我的代碼並選擇使用承諾。告訴我它是否適合你。 –

相關問題