繁体   English   中英

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

[英]Handle queries inside loop in 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 );// 应该包含所有查询的输出。

只需使用闭包生成临时作用域

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

理论

执行上下文

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

作用域链

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

解释

匿名函数帮助我们创建一个新的作用域“阻塞” tVal的值,因为当执行时,一个新的scope被添加到包含val值的scope chain中。 这个新的scope父母孩子scope在至极的for loop执行,当循环下去tVal变化,但val包含在scope ,距离变化的安全。

在执行查询中使用 loop & 的最佳标准方法是使用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
    });


})

尝试“让”而不是“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