foreach在mysql插入之前进行操作

时间:2017-01-20 03:52:00

标签: javascript node.js asynchronous

我仍然很难理解这些步骤是如何运行的。

基本上我正在使用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 

我只是不明白为什么它首先会对插入颜色进行预处理的机制。

有关信息,我能够使用异步

生成我想要的预期输出
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 个答案:

答案 0 :(得分:1)

让我在这里展示另一个简化案例:

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

如果我在Chrome控制台中尝试输出:

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都会继续循环,一旦完成,就会按顺序执行回调。请注意,undefined执行完毕后会在那里打印colors.forEach,它代表函数的return值。请尝试将其更改为colors.map

让我再举一个例子:

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

如您所见,setTimeout位于无限while循环之前,它意味着立即执行(0毫秒后),但它永远不会执行。当javascript VM读取第一行时,它将安排稍后调用回调,然后它将读取第二行并且它将被卡在那里。在堆栈中的其他所有内容都完成执行之前,永远不会调用setTimeout回调。

现在同样的事情发生在connection.query上。它的回调计划稍后调用。它也可能需要十几毫秒或更长时间(取决于网络和数据库)才能被调用。因此,当它被称为其他一切已被执行时。

现在async.eachSeries不像forEach那样迭代。它等待它被调用回调,无论需要多长时间。

因此,如果您在connection.query回调之外调用回调,那么可能会得到与forEach相同的结果(这是错误的代码,不要更改您的代码,它是&#39;只是为了你的教育):

    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);
       });                           

这种情况发生的原因是seriesCallback结果准备好之前就已connection.query,即使它已放在其后面。

如果仍然不清楚,请随意在评论中提出更多问题。