Javascript Knex批量插入在传递到下一个异步操作之前不等待完成

Javascript Knex批量插入在传递到下一个异步操作之前不等待完成,javascript,asynchronous,async-await,knex.js,Javascript,Asynchronous,Async Await,Knex.js,我遇到了一个问题,我将多个元素批量插入到一个表中,然后我立即从该表中获取最近插入的最后X个元素,但当我这样做时,元素似乎还没有完全插入,即使我正在使用async wait等待异步操作 我正在做一个像这样的批量插入 const createElements = elementsArray => { return knex .insert(elementsArray) .into('elements'); }; 然后我有了一种方法,可以立即访问插入的X

我遇到了一个问题,我将多个元素批量插入到一个表中,然后我立即从该表中获取最近插入的最后X个元素,但当我这样做时,元素似乎还没有完全插入,即使我正在使用async wait等待异步操作

我正在做一个像这样的批量插入

const createElements = elementsArray => {
    return knex
        .insert(elementsArray)
        .into('elements');
};
然后我有了一种方法,可以立即访问插入的X元素:

const getLastXInsertedElements = (userId, length, columns=['*']) => {
    return knex.select(...columns)
            .from('elements').where('userId', userId)
            .orderBy('createdAt', 'desc')
            .limit(length);
}
最后,在获取这些元素之后,我获取它们的id并将它们保存到另一个表中,该表利用了最近添加的元素的元素id

所以我有点像:

// A simple helper function that handles promises easily
const handleResponse = (promise, message) => {
    return promise
        .then(data => ([data, undefined]))
        .catch(error => {
            if (message) {
                throw new Error(`${message}: ${error}`);
            } else {
                return Promise.resolve([undefined, `${message}: ${error}`])
            }
        }
    );
};

async function service() {
    await handleResponse(createElements(list), 'error text'); // insert x elements from the list
    const [elements] = await handleResponse(getLastXInsertedElements(userId, list.length), 'error text') // get last x elements that were recently added

    await handleResponse(useElementsIdAsForeignKey(listMakingUseOfElementsIds), 'error text'); // Here we use the ids of the elements we got from the last query, but we are not getting them properly for some reason
}
所以问题是: 有些时候,当我执行
getLastXInsertedElements
时,似乎
元素还没有插入完毕,即使我正在使用async/wait等待,你知道为什么吗?也许是我不知道的与批量插入有关的东西?一个重要的注意事项是,所有元素总是在某个时刻正确地插入到表中,这一点似乎没有得到承诺的尊重(异步操作返回knex.insert的成功)

更新1: 出于测试目的,我曾尝试将插入后的select设置为5秒的setTimeout,但问题似乎仍然存在,这真的很奇怪,似乎有人会认为插入和select之间的5秒足以获取所有数据


我希望在select查询中可以从
getLastXInsertedElements
一致地访问刚刚插入的所有X元素。

我不是100%确定,但我猜knex函数在默认情况下不会返回PROMITE(而是查询的生成器对象)。该生成器有一个名为
then
的函数,该函数将生成器转换为承诺。因此,您可以尝试添加一个呼叫:

... 
limit(length)
.then(x => x); // required to transform to promise
可能尝试调试返回值的实际类型。也许这仍然不是一个承诺。在这种情况下,您可能不使用
asyncwait
,但需要使用
then
语法,因为它可能不是真正的js承诺,而是它们自己的实现


也可以在knex中看到这个关于标准js承诺的问题,理论上,它应该是有效的

你说“似乎”。。。更清晰的问题解释可能会有所帮助


我可以说问题在于你有
elements.length=list.length-n
其中
n>0
;在您的代码中,您的
列表中没有关于
userId
属性的详细信息;问题的一个可能原因是
列表中的某些元素没有正确设置的
userId
属性。

您使用的是哪个数据库,插入的数据列表有多大?您还可以测试是否在事务中插入和
getLastXInsertedElements
,如果这隐藏了您的问题

在事务中执行这些操作也会迫使knex对两个查询使用相同的连接,因此它可能会导致跟踪这是从哪里来的

强制查询使用相同连接的另一个技巧是将池的最小和最大配置设置为1(仅用于测试,并行性确实是这里的问题)

另外,由于您没有提供完整的复制代码,我怀疑混合中还有其他原因导致这种奇怪的行为。通常(但并非总是)这种不应该发生的奇怪情况是由使用库的其他地方的用户错误引起的


如果有更多信息,我会更新答案。完整的复制代码将是最重要的信息。

尝试使用承诺而不是async/await链接所有语句,得到了相同的结果,有时列表不包含插入的所有元素,就像在
select
启动时操作尚未完成一样。奇怪的是,我添加了一个setTimeout,在进行选择之前等待5秒,问题似乎是一样的,这很奇怪,人们会认为5秒就足以完成插入(我的列表只包含大约100行要插入)嗯,然后我会说问题不是由显示的代码造成的,信息丢失了。使用调试器应该可以帮助您了解正在发生的事情。PS:你不能将js promise与大多数其他promise实现混为一谈。我说“似乎”是因为我不完全理解knex的全部行为,如果我确保我知道问题所在,我就不会为创造力留下空间,我不希望这样
userId
是一个来自localStorage的整数,根据我所做的测试,即使结果不一致,它也总是正确的,所以我没有添加关于它的信息,因为它工作正常,我只是复制和粘贴了这些方法,并试图清理它们以使它们易于理解。你的数组有多大?您尝试过使用
batchInsert
吗?我们认为我们观察到了相同的问题。你是怎么解决这个问题的?