简体   繁体   English

javascript中循环结束后,如何执行语句?

[英]How can I execute a statement AFTER a loop finishes in javascript?

I'm querying a mongo database to retrieve the tiles for the display in rougelike game. 我正在查询mongo数据库,以检索类似胭脂游戏中显示的图块。 This is the function I use: 这是我使用的功能:

function get_display(){
    var collections = ['austinsroom'];
    var db  = mongojs(uri, collections);
    var temphtml = '';

    for(var j = 0; j < 3; j++) {
        console.log("y=" + String(j));
        db.austinsroom.find({"y": j}, {}).sort({"x": 1}, function(err, records) {
            if(err) {
                console.log("There was an error executing the database query.");
                return;
            } 
            var i = records.length;
            while(i--) {
                temphtml += records[i].display;
            }   
            temphtml += '<br>';
            //console.log(temphtml);
            //return temphtml;
            //THE ONLY WAY I CAN GET ANYTHING TO PRINT IN THE CONSOLE IS IF I PUT IT INSIDE THE LOOP HERE
            });
        //console.log(temphtml);
        //return temphtml;
        //THIS DOES NOTHING
    }
    //console.log(temphtml);
    //return temphtml;
    //THIS DOES NOTHING
}
get_display();

If I put the console.log(temphtml) inside the loop, it prints out three times which isn't what I want. 如果我将console.log(temphtml)放入循环中,它将打印出三遍,这不是我想要的。 I only want the final string (ie ...<br>...<br>...<br> . Also I can't ultimately return the temphtml string, which is actually the important thing. Is this some quirk of javascript? Why would it not execute statements after the loop? 我只想要最后一个字符串(即...<br>...<br>...<br> 。我也最终不能返回temphtml字符串,这实际上很重要。这是javascript?为什么循环后不执行语句?

Also: is there a better way to retrieve every element of a grid that's stored in a mongo database, in order, so it can be displayed properly? 另外:有没有更好的方法来按顺序检索存储在mongo数据库中的网格的每个元素,以便可以正确显示? Here's what the mongo documents look like: 这是mongo文档的样子:

{
    "_id": {"$oid": "570a8ab0e4b050965a586957"},
    "x": 0,
    "y": 0,
    "display": "."
}

Right now, the game is supposed to display a " . " in all empty spaces using the x and y values for the coordinates. 现在,该游戏应该使用x和y值作为坐标在所有空白区域中显示“ . ”。 The database is indexed by "x" values. 数据库通过“ x”值索引。

See async.whilst . 参见async.whilst You want flow control of the for loop, for which this provides a callback to control each loop iteration. 您需要for循环的流控制,为此它提供了一个回调来控制每个循环迭代。

var temphtml = "",
    j = 0;

async.whilst(
  function() { return j < 3 },
  function(callback) {
    db.austinsroom.find({"y": j }, {}).sort({"x": 1}, function(err, records) 
      temphtml += records.map(function(el) {
          return el.display;
      }).join("") + '<br>';
      j++;
      callback(err);
    });
  },
  function(err) {
     if (err) throw err;
     console.log(temphtml);
  }
)

Either that or use Promise.all() on collected promises to return "one big result". 要么对已收集的Promise.all()使用Promise.all()返回“一个大结果”。 But you would also need to switch to promised-mongo from mongojs , as the nearest equivalent, since there are more mongodb drivers that actually support promises. 但是,您还需要从mongojs切换到mongojs promised-mongo ,作为最接近的等效项,因为实际上有更多的mongodb驱动程序支持promise。 That one is just the direct fork from mongojs : 那只是mongojs的直接分支:

var temphtml = "",
    j = 0,
    promises = [];

for ( var j=0; j < 3; j++ ) {
   promises.push(db.austinsroom.find({"y": j }, {}).sort({"x": 1}).toArray());
   promises.push('<br>');   // this will just join in the output
)

Promise.all(promises).then(function(records) {
    temphtml += records.map(function(el) {
        return el.display;
    }).join("");
})

Not exactly the same thing, since it's one list output and not three, but the point is that the Promise objects defer until actually called to resolve, so you can feed the paramters in the loop, but execute later. 不完全相同,因为它是一个列表输出而不是三个列表,但要点是Promise对象推迟到实际调用解析为止,因此您可以在循环中提供参数,但稍后再执行。

I do not use MongoDB but from what I am reading it is asynchronous. 我不使用MongoDB,但根据我的阅读,它是异步的。 So what is happening is your db.austinsroom.find call fires another "thread" and returns to the for loop to continue the next iteration. 因此,正在发生的是您的db.austinsroom.find调用触发了另一个“线程”,并返回到for循环以继续下一次迭代。

One way to do what you want is have a check at the end of your db.austinsroom.find function to see if you're done with the for loop. 一种执行所需操作的方法是在db.austinsroom.find函数的末尾进行检查,以查看是否已完成for循环。 Something like: 就像是:

function get_display()
{
    var collections = ['austinsroom'];
    var db  = mongojs(uri, collections);
    var temphtml = '';
    var doneCounter = 0;

    for(var j = 0; j < 3; j++)
    {
        console.log("y = " + String(j));
        db.austinsroom.find({"y": j}, {}).sort({"x": 1}, function(err, records)
        {
            if(err)
            {
                console.log("There was an error executing the database query.");
                return;
            } 
            var i = records.length;
            while(i--)
            {
                temphtml += records[i].display;
            }   
            temphtml += '<br>';

            // we're done with this find so add to the done counter
            doneCounter++;

            // at the end, check if the for loop is done
            if(doneCounter == 3)
            {
                // done with all three DB calls
                console.log(temphtml);
            }
       });
    }
}

This is probably not the best way as I know nothing about MongoDB but it should put you on the right path. 这可能不是最好的方法,因为我对MongoDB一无所知,但它应该使您走上正确的道路。

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

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