我在使用查询(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,而不是上次迭代时给出的变量?
答案 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])
});
}
编辑:这篇文章非常适合澄清为什么以及如何处理异步:
答案 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,通常是我在其中进行任何字符串操作,循环等的地方,只是为了使其在代码中更明显地进行分段。