【问题标题】:Handle async DB calls处理异步数据库调用
【发布时间】:2018-01-28 21:59:36
【问题描述】:

我用 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”传递给 DB 函数,然后传递给 DB Query,如果一切正常,我会执行“this.数据库查询函数中的 emit()"。但对我来说,这看起来很脏,可重复使用也不多。

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

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

感谢您的帮助。

【问题讨论】:

  • 您也可以让askDatabaseForInput 接受回调。只是一个普通的论点。
  • 我被卡住了。这对我的情况有什么帮助?
  • 看起来很像:stackoverflow.com/questions/14220321/…。不能采用异步值,并且返回是同步的。 Javascript 根本无法做到这一点,您的数据库调用只是异步的。因此,必须异步使用来自数据库的结果 - 周期。

标签: javascript node.js asynchronous synchronous alexa


【解决方案1】:

所以你可以做两件事:

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

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

希望对你有帮助

【讨论】:

  • 哦,是的。我昨天真的被困住了。谢谢杰克和瑞恩。当然,在这里使用回调会有所帮助。它不像“askDatabaseForInput()”只会返回信息那样“好看”,而是使用“askDatabaseForInput(function(err, data) { xxx});”它至少保留了它所属的逻辑。
猜你喜欢
  • 2018-10-25
  • 2014-08-05
  • 2018-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多