在继续之前,NodeJS等待从sql.get分配变量

时间:2017-07-12 20:28:19

标签: node.js sqlite asynchronous async-await

我知道sqlite(而不是sqlite3)模块会批量处理请求。我需要从数据库中获取一个值,分配它,然后用它做一些处理。但是,在完成所有处理之后,才会返回从数据库中获取值的函数。

我需要发生以下三件事之一:

  1. 立即返回的功能
  2. 暂停代码,直到分配了myEvent.id
  3. 让sql.get立即返回

    myEvent.id = generateEventID();
    ///do stuff with myEvent.id
    
    function generateEventID() {
    return sql.get('SELECT * FROM settings WHERE name = "eventID"').then(row => {
      if (!row) return message.reply("a database error occured while generating an ID");
      currentID = row.intValue + 1;
      console.log("New eventID created: " + currentID);
      sql.run(`UPDATE settings SET intValue = ${row.intValue + 1} WHERE name =  "eventID"`);
      return currentID;
      });
    }
    

2 个答案:

答案 0 :(得分:0)

很遗憾,您无法直接返回Id函数,因为sql.get(...)是异步的。

解决此问题的一种可能方法是将callback函数作为参数传递给generateEventID(),然后让调用者等待callback函数调用之前进一步发展。

因此你会看起来像这样。

var doStuffWithEventId = function(eventId) {
    // Do more stuff.
}

generateEventID(doStuffWithEventId);


function generateEventID(callback) {
    return sql.get('SELECT * FROM settings WHERE name = "eventID"').then(row => {
        if (!row) return message.reply("a database error occured while generating an ID");
        currentID = row.intValue + 1;
        console.log("New eventID created: " + currentID);
        sql.run(`UPDATE settings SET intValue = ${row.intValue + 1} WHERE name =  "eventID"`);
        return callback(currentID); // Call function doStuffWithEventId with value of currentID variable
    });
}

这是完成您尝试做的事情的一种方式。

请注意这里。

  1. 您通常会在返回任何内容之前等待update操作。
  2. 您预计Id将始终是增量1.数据库并不总是这样做。所以你可能会措手不及。
  3. 您的代码假定数据库操作将始终成功。您通常希望处理在进行外部调用时可能引发的潜在异常。

答案 1 :(得分:0)

正如您所说,您的代码应以特定顺序提供三个主要功能:

  1. 从数据存储中获取结果(在本例中为SQL数据库)。
  2. 对获得的数据执行特定操作(简称 你的sniippet中的//do more stuff
  3. 对您的数据存储执行UPDATE查询。
  4. 因此,您提供的实现逻辑是错误的,因为它无法按特定顺序执行三个操作。不要忘记默认情况下所有节点调用都是异步,在这种情况下,您无法强制执行所需的同步。要解决此问题,您应该执行以下步骤:

    1. 从您的数据存储中获取结果。 (已经完成)。
    2. 对获得的数据执行特定操作。这必须在sql.get()回调内部或者承诺解决后完成(因为在这种情况下你使用了promises)。
    3. 对您的数据执行操作的方法(即步骤2)应返回新的承诺。一旦此承诺得到解决,您就可以致电UPDATE操作,这样您就可以确保您的实施符合您的所有要求。
    4. 现在,我就是这样做的:

      generateEventID();
      
      function doMoreStuff(eventId){
        return new Promise(function(resolve, reject){
          //do your stuff
          if(err){
            reject(err)
          }else{
            resolve()
          }
        })
      }
      
      function generateEventID() {
        return sql.get('SELECT * FROM settings WHERE name = "eventID"').then(row => {
          if (!row) return message.reply("a database error occured while generating an ID");
          currentID = row.intValue + 1;
          console.log("New eventID created: " + currentID);
          doMoreStuff(currentID).then(function(){ //At this point your operations with currentId will have finished already
            sql.run(`UPDATE settings SET intValue = ${row.intValue + 1} WHERE name =  "eventID"`);
          });
        });
      }
      

      我真的希望这有帮助!

      编辑:不要忘记使用.catch()

      实现承诺的错误处理