用解析文本文件的 after promise 填充数据库

Filling a database with after promises parsing a text file

提问人:Howl 提问时间:2/6/2022 更新时间:2/6/2022 访问量:81

问:

我正在尝试使用 bluebird 和 sqlite3 构建一个数据库来管理很多“成分”。 到目前为止,我已经设法解析了一个文件,并使用正则表达式从中推断出一些数据。

每当一行与正则表达式匹配时,我都想在数据库中搜索是否已经插入了同名元素,如果是这样,则跳过该元素,否则必须插入。 问题在于某些元素入了不止一次。 代码部分有效,我说它部分有效,因为如果我删除检查是否存在同名元素的代码行,重复的行会多得多。

下面是这段代码:

 lineReader.eachLine(FILE_NAME, (line, last, cb) => {
      let match = regex.exec(line);
      if (match != null) {
          let matchedName = match[1].trim();

          //This function return a Promise for all the rows with corresponding name
          ingredientsRepo.getByName(matchedName)
             .then((entries) => {
                 if (entries.length > 0) {
                     console.log("ALREADY INSERTED INGREDIENT: " + matchedName)
                 } else {
                     console.log("ADDING " + matchedName)
                     ingredientsRepo.create(matchedName)
                 }
          })   
      }
 });

我知道我错过了一些关于承诺的东西,但我不明白我做错了什么。

下面是 Both 和 的代码:getByName(name)create(name)

create(name) {
    return this.dao.run(
        `INSERT INTO ingredients (name) VALUES (?)`,
        [name]
    )
}


getByName(name) {
    return this.dao.all(
        'SELECT * FROM ingredients WHERE name == ?',
        [name]
    )
}
node.js sqlite promise 蓝鸟

评论


答:

0赞 Ivan Bacher 2/6/2022 #1

ingredientsRepo.getByName(matchedName)返回一个 promise,这意味着它是异步的。我也猜测这是异步的,因为您正在将某些内容插入到数据库中。ingredientsRepo.create(matchedName)

循环不会等待这些异步函数完成。因此,当第一次迭代调用 时,循环可能已经在第 50 次迭代中出现。.then(...)

因此,假设前 10 个元素具有相同的名称。好吧,由于异步函数需要一些时间才能完成,因此在循环的第 20 次迭代之前,该名称不会插入到数据库中。因此,对于前 10 个元素,该名称在数据库中不存在。

这是一个时机问题。

评论

0赞 Howl 2/6/2022
我是这么认为的,我尝试使用 ''' await ingredientsRepo.getByName(matchedName)...''' 调用 getByName wait,但它没有改变 reuslt
0赞 Ivan Bacher 2/7/2022
我认为这行不通。通过添加 await,您所做的只是在您传入的回调中返回一个 promise。它不会等待它完成,然后再进入下一个迭代。看看 async.js,特别是队列或瀑布控制流技术。lineReader.eachLine()