【问题标题】:Can't use value resolved from and returned from promise不能使用从 promise 解析和返回的值
【发布时间】:2018-02-09 20:13:55
【问题描述】:

在下面的代码中,我抓取了一个 Table 对象(来自 mysql/xdevapi)。 getSchema() 和 getTable() 方法返回对象,而不是 promise。我的目的是让这个函数返回一个我可以在其他代码中同步使用的 Table 对象(实现的值)。

// dbutils.js    
var mysqlx = require('@mysql/xdevapi');
var settings = require('./settings');

exports.getTable = (tableName) => {
  return mysqlx.getSession(settings.connectionProperties)
  .then(dbSession => {
    let table = dbSession.getSchema('shizbot').getTable(tableName);
    console.log("dbutils.getTable is returning table: " + table.getName())
    return table;
  })
  .catch(error => {
    console.log(error);
  })
}

但是,当我从此代码调用上述方法时,我得到 TypeError,试图在返回的 Table 对象上执行一个方法,并且 Table 对象的值记录为 {}。 (顺便说一句,我还有其他代码在上面的 then() 方法中使用 Table 对象时很好。)

// db_user.js
var dbutils = require('./dbutils');

function getUserTable() {
  let table = dbutils.getTable('user');
  console.log("table: " + JSON.stringify(table));  //  table: {}  ???
  console.log("dbuser.getUserTable is returning table: " + 
  table.getName()) // TypeError: table.getName is not a function
return table;
}

此外,我的日志显示了意外的事件顺序。到底是怎么回事?我意识到我可以(并且可能应该)利用承诺并在下游重写我的代码,但为什么这段代码不起作用?我正在尝试更好地了解如何混合异步和同步代码。

谢谢!

Console Output:
running /authenticate route.
table: {}
Error while authenticating: TypeError: table.getName is not a function
POST /admin/authenticate 500 24.089 ms - 40
dbutils.getTable is returning table: user

【问题讨论】:

  • getUserTable() 中,table 是一个承诺,而不是它解析为的值。
  • 另外,您指出 getSchema()getTable() 方法返回对象,而不是承诺,但您忘记了 getSession() 确实返回承诺,即为什么我的上述说法是正确的。您不能同步履行承诺,但您可以将 getUserTable() 声明为 async 并改为使用 let table = await dbutils.getTable('user'),但随后 getUserTable() 将返回解析为 table 的承诺。
  • 谢谢@PatrickRoberts。没有争议,只是困惑。我得到了你建议的 async/await 策略,但我仍然不明白我是如何返回一个承诺的。 (dbSession) => { session ...} 不会将其解析为会话值吗?如果根据 mysql api,getSchema.getTable 返回了一个承诺,那么我明白你的意思,但根据文档,情况并非如此。 see api 。我有其他代码在 then 方法中使用 table 对象就好了。只有当我返回该值时,我才会看到问题。
  • 您的 API 链接指的是 dbSession 对象的文档,但 mysqlx.getSession() 如我所说返回一个承诺。
  • 经过一番思考,我意识到我对此的盲点,我接受@PatrickRoberts 对此的回答。我现在看到我错误地假设如果一个 promise.then 解析为一个值对象,那么我可以期望在这一点上同步使用该对象,我不能,除非我引入一些机制(如 async/await)等待该决议。

标签: javascript mysql asynchronous promise synchronous


【解决方案1】:

我相信这是因为您的 console.log 语句在您的异步 table.getTable('user') 完成之前执行。

【讨论】:

    【解决方案2】:

    您的console.log() 语句在异步函数准备好之前执行。您还需要 .then() 函数的 .then() 语句,以便您的数据现在位于我在代码中显示的表格中:

    // db_user.js
    var dbutils = require('./dbutils');
    
    function getUserTable() {
      dbutils.getTable('user')
        .then(function(table) {
          console.log("table: " + JSON.stringify(table));
          console.log("dbuser.getUserTable is returning table: " + table.getName());
          return table;
        })
    }
    

    请尝试我的代码并告诉我错误

    【讨论】:

    • 只是为了澄清这从根本上改变了getUserTable() 本身应该如何被调用,所以如果调用者期望一个同步的结果,就不可能给它一个。我将删除我的反对票,因为您的回答不再明显错误,但您需要解释这种差异。
    猜你喜欢
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    相关资源
    最近更新 更多