与节点js中的回调混淆

时间:2017-04-07 06:02:57

标签: node.js

我在nodejs中有这个查询。请修改代码,使其在每次迭代时查询数据库,并将每次结果存储在结果数组中。 for循环执行结束后,它将被发送到我的回调函数。当我尝试在result.push(数据)之后进行回调(结果)时,它会工作但由于for循环它将发送几乎rows.length次。

function query_database(req,callback){     结果= [];

class_code=req.body.class;
branch=req.body.branch;
year=req.body.year;
start_date=req.body.start_date;
end_date=req.body.end_date;
flag=false;
query='select id,rollno from student where branch="'+branch+'" and class="'+class_code+'" and year="'+year+'"';

//console.log(query);
connection.query(query, function(err, rows, fields) {
    if (!err){
        query_total_working_days(start_date,end_date,branch,class_code,year,function(err,data){
            if(err){

            }
            else{
                total_days=data;
                for(index=0;index<rows.length;index++){
                    query_attendance(rows[index].id,rows[index].rollno,start_date,end_date,total_days,function(err,data){
                        if(err){

                        }
                        else{
                            result.push(data)
                        }
                    });
                }

            }
        })
        callback(null,result)

    }

    else
        console.log('Error while performing Query.');
});

}

2 个答案:

答案 0 :(得分:0)

您的代码可能会像这样简化:

function query_database(callback) {
  let result = [];
  query_all(function(rows) {
    for (let i = 0; i < rows.length; i++) {
      query_row(rows[i], function (data) {
        result.push(data); // (2)
      }); 
    }
  })
  callback(result); // (1)
}

问题是你不能确定(2)在(1)之前完成。实际上,在调用所有(2)之前调用(1)。

要使其正确,您需要更改为以下代码:

function queryDatabase(callback) {
  let result = [];
  queryAll(function(rows) {
    let i = 0;
    let rowCallBack = function (data) {
      result.push(data);
      i++;
      if (i == rows.length) {
        callback(result);      
      } else {

        queryRow(row[i], rowCallBack);
      }
    };

    queryRow(row[i], rowCallBack);
  })
  callback(result); // (1)
}

答案 1 :(得分:0)

1。如果query_attence是同步的......

这应该可以胜任。

/* global req, connection, query_total_working_days, query_attendance, callback */

// assuming req is a correct request.
var class_code = req.body.class,
    branch = req.body.branch,
    year = req.body.year,
    start_date = req.body.start_date,
    end_date = req.body.end_date,
    // this `flag` is never used, why ?? you can remove it.
    flag = false,
    // assuming this is a query that represent a correct SQL query
    query = 'select id,rollno from student where branch="' + branch + '" and class="' + class_code + '" and year="' + year + '"';

// assuming connection is a correct sql connection object
// fields is never used, you can remove it.
connection.query(query, function(err, rows, fields) {
    if (err) {
        return console.log('Error while performing Query.');
    }

    // assuming query_total_working_days is a correct « async » function.
    query_total_working_days(start_date, end_date, branch, class_code, year, function(err, data) {
        var total_days,
            result = [],
            index,
            next = function (err, data) {
                if (err) {
                    return ; // you should provide a code for this error.
                }

                // result is not declared, initially. So I create it above.
                result.push(data);
            };

        if (err) {
            return ; // you should provide a code for this error
        }

        total_days = data;

        // assuming query_attendance is a correct « sync » function.
        for (index = 0; index < rows.length; index++) {
            // I move the `next` callback not it this loop because expression function should not be declared in loop.
            query_attendance(rows[index].id, rows[index].rollno, start_date, end_date, total_days, next);
        }

        // assuming callback is a correct function.
        callback(null, result);
    });
});

2。但是如果query_attence是asynchrone(可能)

您的问题是:callback将在所有query_attendance完成之前执行。因此,您的result数组将不包含您想要的所有条目。

所以在这种情况下。您应该使用模块async作为示例https://github.com/caolan/async/blob/v1.5.2/README.md

如果结果的顺序很重要,请在series中使用。

如果您的结果顺序不重要,为了更快,请在parallele

中使用它
/* global req, connection, query_total_working_days, query_attendance, callback, async */

// assuming req is a correct request.
var class_code = req.body.class,
    branch = req.body.branch,
    year = req.body.year,
    start_date = req.body.start_date,
    end_date = req.body.end_date,
    // this `flag` is never used, why ?? you can remove it.
    flag = false,
    // assuming this is a query that represent a correct SQL query
    query = 'select id,rollno from student where branch="' + branch + '" and class="' + class_code + '" and year="' + year + '"';

// assuming connection is a correct sql connection object
connection.query(query, function(err, rows, fields) {
    // fields is never used, you can remove it.
    if (err) {
        return console.log('Error while performing Query.');
    }

    // assuming query_total_working_days is a correct « async » function.
    query_total_working_days(start_date, end_date, branch, class_code, year, function(err, data) {
        var total_days,
            parallels = [],
            next = function (next) {
                query_attendance(rows[index].id, rows[index].rollno, start_date, end_date, total_days, function (err, data) {
                    if (err) {
                        return ; // you should provide a code for this error 
                    }

                    // result is not declared, initially. So I create it.
                    next(null, data);
                });
            };

        if (err) {
            return ; // you should provide a code for this error
        }

        total_days = data;

        // assuming query_attendance is a correct « async » function.
        // we use let to not set value to variable objet in order to kept the current value of `index` for each call of `next`.
        for (let index = 0; index < rows.length; index++) {
            parallels.push(next);
        }

        // assuming async is the async npm module. In this case, result order have no importance.
        async.parallel(parallels, function (results) {
            // assuming callback is a correct function.
            callback(null, results);
        });
    });
});

注意:我无法测试此代码,如果您有错误,请告诉我。