处理异步数据库调用

Handle async DB calls

我用 node.js 做了几个项目,我知道异步行为,并且通常应该使用回调函数等。但困扰我的是以下内容。

我正在开发一项 Alexa 技能,并且我有一个处理用户意图的函数:

'MyFunction': function() {
  var toSay = ""; // Holds info what Alexa says
  
  // Lot of checks and calculations what needs to be said by Alexa (nothing special)
  if(xyz) {
    toSay = "XYZ";
  }else if(abc) {
    toSay = "ABC";
  }else{
    toSay = "Something";
  }
  
  // Here is the "tricky" party
  if(someSpecialEvent) {
    toSay += " "+askDatabaseForInput(); // Add some information from database to string
  }
    
  this.emit(':ask', toSay, this.t('REPROMT_SPEECH')); // Gives the Info to Alexa (code execution stops here)
}

如代码中所述,有一些代码通常用于找出 Alexa 的输出应该是什么。 只有在罕见事件 "someSpecialEvent" 上,我才需要查询数据库并将信息添加到字符串 "toSay".

查询数据库类似于:

function askDatabaseForInput() { // The function to query the DB
  var params = {
    TableName: "MyTable",
    OtherValues: "..."
  };
  
  // Do the Query
  docClient.query(params, function(err, data) {
    // Of course here are some checks if everything worked, etc.
    var item = data.Items[0]; 
    return item; // Item SHOULD be returned
  });
  
  return infoFromDocClient; // Which is, of course not possible
}

现在我知道,在第一个函数“'MyFunction'”中,我可以将变量 "toSay" 传递给数据库函数,然后传递给数据库查询,如果一切正常,我会在数据库查询函数中执行 "this.emit()"。但是对我来说,这看起来很脏而且不能再使用。

那么有没有一种方法可以使用 "askDatabaseForInput()" 到 return 数据库信息并将其添加到字符串中?这意味着使异步调用同步。

进行同步调用不会影响用户体验,因为代码并没有做任何其他事情,它只是创建字符串并且(可能)正在等待数据库输入。

感谢您的帮助。

所以你可以做两件事:

就像评论的人说你可以使用回调:

function askDatabaseForInput(callback) {
  var params = {
    TableName: "MyTable",
    OtherValues: "..."
  };

  docClient.query(params, function(err, data) {
    if (err) {
      callback(err, null)
    } else {
      var item = data.Items[0]; 
      callback(null, item);
    }
  });
}

或者您可以使用承诺:

function askDatabaseForInput() {
  var params = {
    TableName: "MyTable",
    OtherValues: "..."
  };
  return new Promise(function (resolve, reject) {
    docClient.query(params, function(err, data) {
      if (err) {
        reject(err)
      } else {
        var item = data.Items[0]; 
        resolve(item);
      }
    });
  });
}

然后您可以在调用 askDatabaseForInput 的地方放置一个函数或执行 askDatabaseForInput.then(....)

在函数或 .then 中,您将从数据库中检索到的内容添加到变量 toSay

希望对您有所帮助