NodeJS使用knex迭代太快

时间:2015-11-12 12:46:06

标签: database node.js asynchronous

我在使用查询(knexjs.org)的for循环时遇到了一些困难。让我们开始如何迭代我的数组。我的数组看起来像这样:

[ { module_id: 9, able: '1', will: '1' },
{ module_id: 9, able: '1', will: '1' },
{ module_id: 2, able: '1', will: '1' },
{ module_id: 2, able: '1', will: '1' },
{ module_id: 4, able: '1', will: '1' },
{ module_id: 4, able: '1', will: '1' },
{ module_id: 1, able: '1', will: '1' },
{ module_id: 1, able: '1', will: '1' },
{ module_id: 8, able: '1', will: '1' },
{ module_id: 8, able: '1', will: '1' },
{ module_id: 7, able: '1', will: '1' },
{ module_id: 7, able: '1', will: '1' },
{ module_id: 5, able: '1', will: '1' },
{ module_id: 5, able: '1', will: '1' },
{ module_id: 3, able: '1', will: '1' },
{ module_id: 3, able: '1', will: '1' },
{ module_id: 6, able: '1', will: '1' },
{ module_id: 6, able: '1', will: '1' } ]

然后"有趣"部分来了:

for(var i = 0; i < obj.length; i++) {
        var object = obj[i];
        console.log("has object", object);
        db.knex('interests').where({
            inventory_id: inventory_id,
            module_id: object.module_id
        }).select().limit(1).then(function (result) {
            console.log("MODULE ID", object.module_id);
            if (result.length == 0) {

                db.knex('interests').insert({
                    inventory_id: inventory_id,
                    module_id: object.module_id,
                    could: object.able,
                    would: object.will
                }).then(function (a) {
                });
            } else {
                db.knex('interests').where({
                    inventory_id: inventory_id,
                    module_id: object.module_id
                }).update({
                    could: object.able,
                    would: object.will
                }).then(function (a) {
                });
            }
        });
    }

代码的作用如下:

  • 遍历数组
  • 查询数据库
  • 如果没有结果,请创建一些内容
  • 如果有结果,请更新内容

只有一个问题。 for循环太快。或者,换句话说:查询太慢。为什么?因为 object.module_id 始终是数组中的最后一个 module_id

如何确保它使用for循环中的module_id,而不是上次迭代时给出的变量?

2 个答案:

答案 0 :(得分:1)

实际上,它不是那个节点太快了。这是因为查询工作异步

该过程不会等待查询完成以继续循环。当它们被执行时,循环已经结束。

我建议将所有查询/更新包装在函数中,并将数据作为参数:链接您的回调方法,以便它们可以按预期工作

 var queryinterest =   function(object){
       db.knex('interests').where({
       inventory_id: inventory_id,
       module_id: object.module_id
    }).select().limit(1).then(function (result) {
        if (result.length == 0) {
                insertInterest(object)
        } else {
                updateInterest(object)             
    })
}

然后在主循环中调用它们。

for(var i = 0; i < obj.length; i++) {
        queryInterests(obj[i])
        });
    }

编辑:这篇文章非常适合澄清为什么以及如何处理异步:

Nodejs asynchronous confusion

答案 1 :(得分:0)

在类似的情况下,我将这种方法组合在一起,您可能会觉得有用。 假设您需要从堆栈中获取并解析下一个发票号,或者需要获取用户的全名,然后才能插入或更新记录。 如果您有通用函数,则不必为每个选择编码一个特定的调用,显然会更好:

async function select(table, args, single){
    //assumes you've already configured your knex object database details(hostname, password etc)
    return await knex.select().from(table).where(args).then(function(result) {
            //this formats the result into an easier to parse structure
            let returnObject = {};
            for (const [key, value] of Object.entries(result)) {

                returnObject[key] = value
            }
            //this will toggle whether you want all the rows returned or just the first, handy if you know theres only one match, but not strictly needed for this
            if (single == true) {
                return (returnObject[0])
            } else {
                return (returnObject);
            }
        }
    );
}

然后在您的主循环中:

(async function(){
        const result = await select('tableName',args,true);                        
        console.log(result);
})()

Voila!在将数据用于更新/插入之前,您已经准备好进行其他格式化。在哪里可以看到console.log,通常是我在其中进行任何字符串操作,循环等的地方,只是为了使其在代码中更明显地进行分段。