以下问题来自采访。我能够解决一些问题,但我陷入困境:
修复以下代码中的错误。 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答案 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);
});
});
}
这将允许消费代码将呼叫视为同步操作