在node.js中处理循环内的查询

时间:2015-06-17 12:14:56

标签: node.js

在下面的代码中,val变量值由于异步行为而不断变化并产生意外输出,即在第一个循环的连接查询完成之前,var变量根据第二个循环生成错误输出。处理的最佳方法是什么循环中的查询,避免异步性引起的特性。

    var output = [];
    for ( var j = 0; j < someArr.length ; j++ ) {
         val = someArr[j];//some manipulation of someArr[j]
         connection.query( "select id from someTable where someCol = ?",val, function(err, rows, fields) {
             if ( err ) {
               console.log( err );
             } else {
               output.push( rows[0].someVal );//push query output to this variable
             }
       });
    }

console.log(output); //应该包含所有查询的输出。

3 个答案:

答案 0 :(得分:5)

只需使用闭包来生成临时范围

var output;
    for ( var j = 0; j < someArr.length ; j++ ) {
         tVal = someArr[i];//some manipulation of someArr[i]
         (function(val){
           connection.query( "select id from someTable where someCol = ?",val, function(err, rows, fields) {
               if ( err ) {
                 console.log( err );
               } else {
                 output.push( rows[0].someVal );//push query output to this variable
               }
           });
         })(tVal);
    }

理论

执行上下文

JavaScript是一种单线程语言,这意味着一次只能执行一个任务。当JavaScript解释器最初执行代码时,它首先默认进入全局执行上下文。从这一点开始每次调用一个函数都会导致创建一个新的执行上下文。

范围链

对于每个执行上下文,都有一个与之相关的范围链。范围链包含执行堆栈中每个执行上下文的变量对象。它用于确定变量访问和标识符解析。

说明

匿名函数可帮助我们创建一个“阻止”tVal值的新范围,因为在执行时,新scope被添加到包含scope chain的{​​{1}}值。 这个新val scope,执行scope时,循环继续{{1} }}}但for loop包含在 tVal中,并且不受变体影响。

答案 1 :(得分:2)

最好的&amp;使用循环和标准的标准方法在执行查询中使用 async.eachSeries

因此,使用 async.eachSeries ,它将逐个串行执行。一旦foreach完成,你就可以使用回调。

参考:http://caolan.github.io/async/docs.html#eachSeries

var async = require('async');
var output = [];
connection.query('SELECT * FROM tablename LIMIT 10',function(error,results,filelds){
    if(error) throw err;

    async.eachSeries(results,function(data,callback){ // It will be executed one by one
            //Here it will be wait query execute. It will work like synchronous
            connection.query('SELECT * FROM tablename  where id = 1',function(error,results1,filelds){
                if(error) throw err;

                output.push(results1[0].id)
                callback();
            });

    }, function(err, results) {
        console.log(output); // Output will the value that you have inserted in array, once for loop completed ex . 1,2,3,4,5,6,7,8,9
    });


})

答案 2 :(得分:0)

尝试使用“让” 代替“ var” ,这可能有效

var output = [];
    for ( let j = 0; j < someArr.length ; j++ ) {
         val = someArr[j];//some manipulation of someArr[j]
         connection.query( "select id from someTable where someCol = ?",val, function(err, rows, fields) {
             if ( err ) {
               console.log( err );
             } else {
               output.push( rows[0].someVal );//push query output to this variable
             }
       });
    }