2017-01-20 17 views
0

私はまだステップの実行方法を理解するのに苦労しています。mysqlの挿入前にforeachを実行しています

基本的に私は、foreachのコンピューティングの色をしています、通常のforeachの コードと、それをデータベースに挿入します。

var mysql = require("mysql"), 
    namer = require('color-namer'), 
    async = require('async'); 
var connection = mysql.createConnection({ 
    multipleStatements: true, 
    host  : 'localhost', 
    user  : 'root', 
    password : 'root', 
    database : 'xxxx'}); 
connection.connect(); 




connection.query(
    `SELECT color from sg_fashion_colors limit 10`, 
    function(err, results, fields) { 
     results.forEach(function(elem){ 

      var currentHex = elem['color'], 
       currentColor = namer(currentHex); 
       console.log(currentHex); 
      connection.query(
       `INSERT INTO name_color_pat_test (hex, basic) VALUES (?,?);`, 
       [currentHex,currentColor['basic'][0]['name']] , 
       function(err,data){ 
        console.log("insert"); 
       }    
      ); 
     }); 
    } 
); 

代わりの

color 
insert 
color 
insert 

を行うことが

color 
color 
insert 
insert 
を行います

私はちょうどなぜそれが最初になるのかについてのメカニズムを理解していません各色の上に挿入し、foreachを挿入します。

var colors = ['blue', 'red', 'green']; 
colors.forEach(function(color) { 
    console.log('before setTimeout', color); 
    setTimeout(function() { 
     console.log('after setTimeout', color); 
    }, 0); 
}); 

私はクロームコンソールでそれをしようとした場合:私は、非同期

connection.query(
    `SELECT color from sg_fashion_colors limit 10`, 
    function(err, results, fields) { 
     async.eachSeries(results, function (elem, seriesCallback) { 
       var currentHex = elem['color'], 
       currentColor = namer(currentHex); 
       console.log(currentHex); 
       connection.query(`INSERT INTO name_color_pat_test (hex, basic) VALUES (?,?);`, // insert the SKU inside a database with their primary color 
        [currentHex,currentColor['basic'][0]['name']] , 
        function(err, results, fields) { 
         if (err) throw err; 
         console.log("insert"); 
         seriesCallback(null); 
       });       
     }, function(responsetoendofloop){ 
      console.log("everything has run"); 
     });   
    } 
); 
+1

'connection.query'は非同期です。したがって、forEachループが終了した後にのみコールバック関数が呼び出されることが保証されています**すべて**反復 –

答えて

1

は、私はちょうどここに別の簡略化された場合を示してみましょう使用したい期待される出力を生成することができた情報について

ここに出力:

VM1119:3 before setTimeout blue 
VM1119:3 before setTimeout red 
VM1119:3 before setTimeout green 
<- undefined 
VM1119:5 after setTimeout blue 
VM1119:5 after setTimeout red 
VM1119:5 after setTimeout green 

あなたのスクリプトで起こったことと同じこと。 setTimeoutは、両方ともコールバックを非同期的に呼び出すため、現在のスタックが実行を終了してコールバック関数を呼び出すときにのみコールバックを実行するので、connection.queryに似ています。したがって、どちらの場合も、forEachはループを継続し、コールバックがスケジュールされた順に実行されます。 colors.forEachが実行を終了したときにundefinedがそこに表示され、それが関数のreturn値を表すことに注意してください。代わりにcolors.mapに変更してください。あなたはsetTimeoutをループしながら、無限の前で、(0ミリ秒後)すぐに実行されることを意図しているが、それが実行されることはありません見たよう

setTimeout(function() { console.log('hello'); }, 0) 
while (true) {}; 

は、私はあなたに別の例を挙げましょう。 JavaScriptのVMが最初の行を読み込むと、コールバックが後で呼び出されるようにスケジューリングされ、2行目が読み込まれ、そこにスタックされます。 setTimeoutコールバックは、スタック内の他のすべてが実行を終了するまで呼び出されません。

connection.queryでも同じことが起こります。コールバックは後で呼ばれる予定です。また、(ネットワークとデータベースによっては)呼び出す数十ミリ秒以上かかる場合もあります。だから、それは他のすべてと呼ばれている時点で既に実行されています。

async.eachSeriesforEachのように繰り返されません。どれくらい時間がかかっても、コールバックが呼び出されるまで待ちます。

あなたがconnection.queryコールバックの外にコールバックを呼び出すのであれば、おそらく(これは悪いコードで、あなたのコードを変更しないでください、それはちょうどあなたの教育のためです)forEachと同じ結果を得る可能性があります:

async.eachSeries(results, function (elem, seriesCallback) { 
      var currentHex = elem['color'], 
      currentColor = namer(currentHex); 
      console.log(currentHex); 
      connection.query(`INSERT INTO name_color_pat_test (hex, basic) VALUES (?,?);`, // insert the SKU inside a database with their primary color 
       [currentHex,currentColor['basic'][0]['name']] , 
       function(err, results, fields) { 
        if (err) throw err; 
        console.log("insert"); 

      }); 

      seriesCallback(null); 
     });       

connection.queryより前のseriesCallbackの結果は準備完了です。

まだ明確でない場合は、コメントでさらに質問してください。

+0

非常にクリア!ありがとう – patrick

関連する問題