简体   繁体   English

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

[英]Handle queries inside loop in node.js

In the following code, the val variable value keeps changing due to asynchronous behavior and generates unexpected output ie before connection query for first loop is finished, var variable according to second loop and generates wrong output.What is the best way to handle queries in loop that avoid idiosyncrasies caused by asynchronous nature.在下面的代码中,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 );//should contain output for all queries. console.log( output );// 应该包含所有查询的输出。

Just use a closure to generate a temporary scope只需使用闭包生成临时作用域

 var output; for ( var j = 0; j < someArr.length ; j++ ) { tVal = someArr[j];//some manipulation of someArr[j] (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); }

Theory理论

Execution Context执行上下文

JavaScript is a single threaded language, meaning only one task can be executed at a time. JavaScript 是一种单线程语言,这意味着一次只能执行一个任务。 When the JavaScript interpreter initially executes code, it first enters into a global execution context by default.当 JavaScript 解释器最初执行代码时,它默认首先进入全局执行上下文。 Each invocation of a function from this point on will result in the creation of a new execution context.从这一点开始,每次调用函数都会导致创建一个新的执行上下文。

The Scope Chain作用域链

For each execution context there is a scope chain coupled with it.对于每个执行上下文,都有一个与之耦合的作用域链。 The scope chain contains the variable object for every execution context in the execution stack.作用域链包含执行堆栈中每个执行上下文的变量对象。 It is used for determining variable access and identifier resolution.它用于确定变量访问和标识符解析。

Explanation解释

The anonymous function help us to create a new scope "blocking" the value of tVal because when is executed a new scope is added to the scope chain containing val value.匿名函数帮助我们创建一个新的作用域“阻塞” tVal的值,因为当执行时,一个新的scope被添加到包含val值的scope chain中。 This new scope is a child of the parent scope in wich the for loop is executed, when the cycle continues tVal change but val is contained in the child scope and is safe from the variation.这个新的scope父母孩子scope在至极的for loop执行,当循环下去tVal变化,但val包含在scope ,距离变化的安全。

The best & standard way to use loop & inside the that execute query is use async.eachSeries .在执行查询中使用 loop & 的最佳标准方法是使用async.eachSeries

So using async.eachSeries it will execute one by one in series & once foreach complete you can use callback.因此,使用async.eachSeries它将一个接一个地执行,一旦 foreach 完成,您就可以使用回调。

Ref : http://caolan.github.io/async/docs.html#eachSeries参考: 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
    });


})

Try "let" instead of "var" This might work尝试“让”而不是“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
             }
       });
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM