修复错误! (如何在同步函数内调用异步函数)

时间:2017-05-22 18:57:41

标签: javascript asynchronous synchronous

以下问题来自采访。我能够解决一些问题,但我陷入困境:

修复以下代码中的错误。 DataContainer 是数据库的包装器,为从数据库中提取的数据提供缓存。

调用 fetch 应该通过 DbConnection 从数据库中获取数据。如果获取成功,则应返回 true ;否则它应该返回 false 。如果尚未提取数据,则调用 getData 应返回缓存数据或抛出异常。

function DataContainer(connectionString) {
  var dataFetched = false;
  var dbConnection = DbConnection(connectionString);
}

DataContainer.prototype.getData = function () {
  if (!this.dataFetched)
    throw "Data not fetched!";
  return this.data;
}

DataContainer.prototype.fetch = function () {
  this.dbConnection.getAllData(function (err, result) {
    if (err) {
      delete this.data;
      this.dataFetched = false;
      return false;
    } else {
      this.data = result;
      this.dataFetched = true;
      return true;
    }
  });
}

// Mock of DbConnection for testing purposes:
function DbConnection(connectionString) { }

DbConnection.prototype.getAllData = function (callback) {
  callback(null, [1, 2, 3]);
}

//Expected: 1, 2, 3
var dc = new DataContainer('connection');
if (dc.fetch()) {
  var data = dc.getData();
  for (var i = 0; i < data.length; i++) {
    console.log(data[i]);
  }
}

我尽可能地修复了代码,包括在构造函数中创建新的 DbConnection 对象,使用 this 关键字而不是 var 在构造函数中,并在调用 getData 时将 this 绑定到回调函数(请查看以下代码)。唯一剩下的问题是如何在同步函数中调用异步函数( getData )?!

function DataContainer(connectionString) {
  this.dataFetched = false;
  this.dbConnection = new DbConnection(connectionString);
}

DataContainer.prototype.getData = function () {
  if (!this.dataFetched)
    throw "Data not fetched!";
  return this.data;
}

DataContainer.prototype.fetch = function () {
  this.dbConnection.getAllData(function (err, result) {
    if (err) {
      delete this.data;
      this.dataFetched = false;
      return false;
    } else {
      this.data = result;
      this.dataFetched = true;
      return true;
      }
    }.bind(this));
}

fetch 是一个同步函数,我们不允许它使它异步。 getData 是一个异步函数,我们不允许它使它同步。现在我们如何在 fetch ???

中使用 getData

1 个答案:

答案 0 :(得分:1)

fetch是同步的,但getAllData是异步的,所以问题是如何使getAllData表现得好像是同步函数。您可以实现此目的的一种(也可能是唯一的)方法是使用async/await

DataContainer.prototype.fetch = async function fetch() {
  return await new Promise(resolve => {
      this.dbConnection.getAllData((err, result) => {
        if (err) {
          delete this.data;
          this.dataFetched = false;
        } else {
          this.data = result;
          this.dataFetched = true;
        }
        resolve(this.dataFetched);
      });
  });
}

这将允许消费代码将呼叫视为同步操作