Node.js nodejs如何让for循环等待运行下一个循环实例

Node.js nodejs如何让for循环等待运行下一个循环实例,node.js,mongodb,google-bigquery,async.js,Node.js,Mongodb,Google Bigquery,Async.js,我将nodejs与mongodb和bigquery一起使用 因为bigquery似乎只允许每个命令插入10k个 所以我对主查询进行计数,并循环从10k到多少页 我通过count查询得到了500k,因此有50页或500个循环 如何使循环等待到运行循环的下一页 代码: var limit = 9999; mongo_client.connect(mongo_url, function(err, db) { var query = {'_id.date_visited':{'$gte':'2

我将nodejs与mongodb和bigquery一起使用

因为bigquery似乎只允许每个命令插入10k个

所以我对主查询进行计数,并循环从10k到多少页

我通过count查询得到了500k,因此有50页或500个循环

如何使循环等待到运行循环的下一页

代码:

var limit = 9999;

mongo_client.connect(mongo_url, function(err, db) {
    var query = {'_id.date_visited':{'$gte':'2016-01-01','$lt':'2016-02-01'}};

    db.collection('my_table').count(query,function(err, count){
        var pages = Math.ceil(count/limit);

        console.log("count: "+count);
        console.log("pages: "+pages);

        for(var page=0;page<pages;page++){
            var skip = page * limit;

            console.log("page: "+page);
            console.log("skip: "+skip);

            //HOW TO MAKE THIS loop wait till running next page of the loop
            db.collection('my_table').find(query).sort({'_id.date_visited':1,'_id.hour_visited':1}).limit(limit).limit(skip).toArray(function(err, db_results) { 
                var documents = [];
                async.each(db_results, function (db_resultsx, cb) {
                    documents.push(db_resultsx);

                    if(documents.length == db_results.length) { 
                        //console.log(documents);
                        bigqueryClient
                          .dataset(dataset)
                          .table('my_table')
                          .insert(documents)
                          .then((insertErrors) => {
                            console.log('Inserted');
                            //documents.forEach((row) => console.log(row));
                            console.error(insertErrors);
                            if (insertErrors && insertErrors.length > 0) {
                              console.log('Insert errors:');
                              insertErrors.forEach((err) => console.error(err));
                            }
                          })
                          .catch((err) => {
                            console.error('ERROR:');
                            console.log(err);
                        });
                    }
                });
            });
        }
    });
});
var限制=9999;
连接(mongo_url,函数(err,db){
var查询={''u id.date'u visitored':{'$gte':'2016-01-01','$lt':'2016-02-01'};
db.collection('my_table').count(查询、函数(err、count){
var pages=Math.ceil(计数/限制);
console.log(“count:+count”);
控制台日志(“页面:+页面);
对于(变量页=0;页{
console.log('Inserted');
//documents.forEach((行)=>console.log(行));
控制台错误(插入错误);
if(insertErrors&&insertErrors.length>0){
log('Insert errors:');
insertErrors.forEach((err)=>console.error(err));
}
})
.catch((错误)=>{
console.error('error:');
控制台日志(err);
});
}
});
});
}
});
});

我可能会将for循环替换为,这样您就可以决定何时进行下一次循环迭代,而且由于
async.eachSeries
一次只运行一个操作,因此不会遇到相同的错误

编辑:

var limit = 9999;

mongo_client.connect(mongo_url, function(err, db) {
    var query = {'_id.date_visited':{'$gte':'2016-01-01','$lt':'2016-02-01'}};

    db.collection('my_table').count(query,function(err, count){
        var pages = Math.ceil(count/limit);

        console.log("count: "+count);
        console.log("pages: "+pages);

        for(var page=0;page<pages;page++){
            var skip = page * limit;

            console.log("page: "+page);
            console.log("skip: "+skip);

            //HOW TO MAKE THIS loop wait till running next page of the loop
            db.collection('my_table').find(query).sort({'_id.date_visited':1,'_id.hour_visited':1}).limit(limit).limit(skip).toArray(function(err, db_results) { 
                var documents = [];
                async.each(db_results, function (db_resultsx, cb) {
                    documents.push(db_resultsx);

                    if(documents.length == db_results.length) { 
                        //console.log(documents);
                        bigqueryClient
                          .dataset(dataset)
                          .table('my_table')
                          .insert(documents)
                          .then((insertErrors) => {
                            console.log('Inserted');
                            //documents.forEach((row) => console.log(row));
                            console.error(insertErrors);
                            if (insertErrors && insertErrors.length > 0) {
                              console.log('Insert errors:');
                              insertErrors.forEach((err) => console.error(err));
                            }
                          })
                          .catch((err) => {
                            console.error('ERROR:');
                            console.log(err);
                        });
                    }
                });
            });
        }
    });
});
读完代码后,我认为(根据我的评论更正,
async.timeseries
是正确的选项)是一个更好的选择。下面是一个例子:

async.timesSeries(pages, function(page, next)
{
    var skip = page * limit;
    // ... the rest of your code here

    // when you want the next iteration to start, simply call:
    next();
    /*
    which will tell async that the current iteration is complete, 
    and it can do the next one. You can pass 2 parameters to next,
    the first parameter is an error, and if error is not null it will
    immediately call the function below, and the second parameter is an
    item you can pass that will be added to an object which will be sent
    as the second parameter in the function below
    */
},
function(err, coll)
{
    /*
    this function will get called if there's an error
    or when all iterations are completed
    */
});

上面的代码将替换for循环

我可能会将for循环替换为,这样您就可以决定下一次循环的迭代时间,而且由于
async.eachSeries
一次只运行一个操作,因此不会遇到相同的错误

编辑:

var limit = 9999;

mongo_client.connect(mongo_url, function(err, db) {
    var query = {'_id.date_visited':{'$gte':'2016-01-01','$lt':'2016-02-01'}};

    db.collection('my_table').count(query,function(err, count){
        var pages = Math.ceil(count/limit);

        console.log("count: "+count);
        console.log("pages: "+pages);

        for(var page=0;page<pages;page++){
            var skip = page * limit;

            console.log("page: "+page);
            console.log("skip: "+skip);

            //HOW TO MAKE THIS loop wait till running next page of the loop
            db.collection('my_table').find(query).sort({'_id.date_visited':1,'_id.hour_visited':1}).limit(limit).limit(skip).toArray(function(err, db_results) { 
                var documents = [];
                async.each(db_results, function (db_resultsx, cb) {
                    documents.push(db_resultsx);

                    if(documents.length == db_results.length) { 
                        //console.log(documents);
                        bigqueryClient
                          .dataset(dataset)
                          .table('my_table')
                          .insert(documents)
                          .then((insertErrors) => {
                            console.log('Inserted');
                            //documents.forEach((row) => console.log(row));
                            console.error(insertErrors);
                            if (insertErrors && insertErrors.length > 0) {
                              console.log('Insert errors:');
                              insertErrors.forEach((err) => console.error(err));
                            }
                          })
                          .catch((err) => {
                            console.error('ERROR:');
                            console.log(err);
                        });
                    }
                });
            });
        }
    });
});
读完代码后,我认为(根据我的评论更正,
async.timeseries
是正确的选项)是一个更好的选择。下面是一个例子:

async.timesSeries(pages, function(page, next)
{
    var skip = page * limit;
    // ... the rest of your code here

    // when you want the next iteration to start, simply call:
    next();
    /*
    which will tell async that the current iteration is complete, 
    and it can do the next one. You can pass 2 parameters to next,
    the first parameter is an error, and if error is not null it will
    immediately call the function below, and the second parameter is an
    item you can pass that will be added to an object which will be sent
    as the second parameter in the function below
    */
},
function(err, coll)
{
    /*
    this function will get called if there's an error
    or when all iterations are completed
    */
});

上面的代码将替换for循环

我认为for循环对于这种情况不是一个好的解决方案,您可以使用如下递归调用进行循环:

function performQuery(queryIndex) {
    if( queryIndex >= limit ) return;

    db.exec('query', function(err, db_result) {
        // your code
        performQuery(queryIndex+1);
    })
}
performQuery(0);

我认为对于这种情况,for循环不是一个好的解决方案,您可以使用如下递归调用进行循环:

function performQuery(queryIndex) {
    if( queryIndex >= limit ) return;

    db.exec('query', function(err, db_result) {
        // your code
        performQuery(queryIndex+1);
    })
}
performQuery(0);

如果您不想使用递归承诺,并且事先知道项目的数量,可以这样做:

// Create a "skip" array (there is certainly a nicer way to do it, with a modulo)
var skips = []; 
for(var page=0;page<pages;page++){
    skips.push(page * limit);
}

// Put your mongoDB read and write code in a function
// (that takes skip in entry and returns an array of documents)
var myMongoDBFunc = function (skip) {
    var documents = [];

    db.collection('my_table')
       .find(query)
       .limit(limit)
       .limit(skip)
       .toArray(function(err, db_results) { 
           ...
       });
   ...
   return documents;
}

// And call it with async.concatSeries that will concatenate the results (documents)
async.concatSeries(skips, myMongoDbFunc, function(err, documents) {
    // Will be called at the end
});
//创建一个“skip”数组(当然有更好的方法,使用模)
var跳过=[];

对于(var page=0;page),如果您不想使用递归承诺,并且您事先知道项目的数量,可以这样做:

// Create a "skip" array (there is certainly a nicer way to do it, with a modulo)
var skips = []; 
for(var page=0;page<pages;page++){
    skips.push(page * limit);
}

// Put your mongoDB read and write code in a function
// (that takes skip in entry and returns an array of documents)
var myMongoDBFunc = function (skip) {
    var documents = [];

    db.collection('my_table')
       .find(query)
       .limit(limit)
       .limit(skip)
       .toArray(function(err, db_results) { 
           ...
       });
   ...
   return documents;
}

// And call it with async.concatSeries that will concatenate the results (documents)
async.concatSeries(skips, myMongoDbFunc, function(err, documents) {
    // Will be called at the end
});
//创建一个“skip”数组(当然有更好的方法,使用模)
var跳过=[];

对于(var page=0;pageWell),您已经在使用。请参阅此行
async.each(db_results,function(db_resultsx,cb){
cb
当您想要向循环的下一次迭代发送信号时,应该执行它。请小心,因为在另一个异步方法之前有一个
if
语句,所以您应该在异步方法(bigQuery)的完成过程中调用该“回调”以及在需要与
if
配对的
else
条件下,否则我们不会发出继续循环的信号。您已经在使用了。请参阅此行
异步。每个(db_结果,函数(db_结果x,cb){
cb
当您想要向循环的下一次迭代发送信号时,应该执行它。请小心,因为在另一个异步方法之前有一个
if
语句,所以您应该在异步方法(bigQuery)的完成过程中调用该“回调”以及在需要与
if
配对的
else
条件下,否则我们不会发出继续循环的信号。因此,我需要向每个序列提供页数,以便循环/迭代那么多次?我稍微误解了此处的意图,在正确查看代码后,可能对您更有用,s因为它将允许回调,所以您只在需要时执行循环的下一部分,并且它将在内默认运行
n
次。它将等待内的代码完成,直到它进入下一个循环?或者我需要做其他事情吗?我是node的新手。我已更新了答案,并进行了更正,这是应该是
async.timeseries
not
async.times
,因为
async.times
会同时运行多次天哪,我的大脑今天工作不正常。我想我一次做的事情太多了。更正了这个示例,所以我需要向每个系列输入页面的数量,以便循环/迭代那么多次?我有点不明白s-read此处的意图,在正确查看代码后可能对您更有用,因为它将允许回调,因此您只在需要时执行循环的下一部分,并且它将在中默认运行
n
次。它将等待内部代码完成,直到进入下一个循环?或do我还需要做些什么?我对node是新手。我已经更新了我的答案,并进行了更正,应该是
async.timeseries
而不是
async.times
,因为
async.times
将同时运行多个时间天哪,我的大脑今天工作不正常。我认为我一次做的事情太多了。更正了示例I li我同意这个想法,但在代码中,它将数据上传到bigquery,所以我希望它等到