for循环在节点js中无法正常工作

时间:2016-01-14 09:04:12

标签: node.js mongodb express monk

我想通过for循环插入多个数据,但是这段代码只添加2或3个数据,然后继续加载加载但没有任何事情发生......

router.post('/addclient' , function (req , res){  
   var finished = false;
   var user = req.body.username;
   for(var i = 0 ; i <30 ; i++){  
       req.body.username = user + i ;  
       objDB.insert("clientList" ,req.body, function(err, data){
           //if(err) console.log(err);        
           if(i>20){
               finished = true;
           }
        });
    }
    if(finished){
             res.redirect('/client/client-list');      
    }
});

5 个答案:

答案 0 :(得分:2)

你做错了。 insert是异步的,因此当i=1的插入完成并调用回调时,可能i等于20且更多,您无法猜测它。您缺少同步和异步概念和差异。

这是针对您的问题的两种解决方案:

首先,一次添加30个项目:

var clientsList = [];
for (var i = 0 ; i < 30 ; i++) {
    clientsList[i] = Ith client object; // create object you want to insert for client i
}
// for example insertAtOnce is a function to insert your list
objDB.insertAtOnce(clientsList,function(err,callback) {
    if (err) console.log("error : ", err);
    res.redirect('/client/client-list');    
});

第二,使用bind

function insertCallback(itr, res, err,callback) {
   if (itr == 29) {
      res.redirect('/client/client-list'); 
   }
}
  ----
for(var i = 0 ; i <30 ; i++){  
   req.body.username = user + i ;  
   objDB.insert("clientList" ,req.body,insertCallback.bind(null, i, res);
} 

答案 1 :(得分:0)

router.post('/addclient', function(req, res) {
    var finished = false;
    var user = req.body.username;
    var i = 0;
    while( true ) {

        if ( i > 20 ) {
            res.redirect('/client/client-list');
        }

        req.body.username = user + i;

        var promise = new Promise();

        objDB.insert("clientList", req.body, function(err, data) {    
            promise.resolve();
        });

        promise.then(function() {

            i++;
            continue;

        });

    }
});

我是从头顶写的。但这里的基本思想是你需要一个无限运行的循环,然后解决一个承诺;分辨率触发继续循环,并递增计数器。

答案 2 :(得分:0)

最好使用 async node.js库,它提供控制流,例如串行运行每个函数。您可以使用 async.whilst() 方法并将代码重构为:

router.post('/addclient', function(req, res) {

    var user = req.body.username,
        count = 0,
        result = { finished = false };      

    async.whilst(
        function () { return count < 30; },
        function (callback) {
            count++;
            req.body.username = user + count.toString();  
            objDB.insert("clientList", req.body, function(err, data){
                if (err) { return callback(err); }  
                result["data"] = data;

                if( count > 20 ) result.finished = true;
                callback(null, result);         
            });     
        },
        function (err, result) {
            if (err) { /* handle err */};
            if (result.finished) res.redirect('/client/client-list');
        }
    );
});

答案 3 :(得分:0)

运行插入函数后调用了一个回调函数。它不是在运行insert之后运行,而不是在循环中运行(它是异步的)。所以在你的代码中,res.redirrect将永远不会被调用,因为在所有循环运行之后,finish将为true。如果你不需要在回答之前完成所有这些插入,你可以这样:

if(i == 29){
         res.redirect('/client/client-list');      
}

否则你需要创建一些队列,例如,我使用异步库https://github.com/caolan/async来创建队列并在队列结束后运行回调。

答案 4 :(得分:0)

使用Promise。我会做类似下面的事情

 router.post('/addclient' , function (req , res){  
   var finished = false;
   var promise = [];
   var user = req.body.username;
   for(var i = 0 ; i <30 ; i++) {  
       req.body.username = user + i;  
       promise.push(new Promise(resolve, reject) {
         objDB.insert("clientList" ,req.body, function(err, data) {
           if(err) {
             reject(err)
             return
           }
           resolve(data)
         })
      })
    }

    Promise.all(promise).then(function() {
      finished = true
    })

    if(finished){
             res.redirect('/client/client-list');      
    }
});