【问题标题】:Is an asynchronous class in Javascript a good idea?Javascript 中的异步类是个好主意吗?
【发布时间】:2016-06-20 10:32:21
【问题描述】:

我希望创建一个从数据库中检索信息并适当设置用户变量的类。

我的问题是,我使用的数据库 API 是异步的,这成为一个问题,因为该类在“完全构造”之前就可以访问(也就是说,构造函数已经返回)。

所需的同步方法

class User{
    constructor(sql){
        this.name = Database.selectQuery(sql);
    }
}
var x = new User(statement);
console.log(x.name); // returns name

当前的异步方法

class User{
    constructor(sql){
        Database.selectQuery(sql, this, function(data, obj){
            obj.name = data;
        });
    }
} 
var x = new User(statement);
console.log(x.name); // returns undefined

我知道我可以向我的构造函数添加回调以使其异步工作,但这是个好主意吗?

【问题讨论】:

  • 如果您在节点中编写代码,那么您正在编写异步代码。您正在使用回调或承诺。
  • 欢迎来到“回调地狱”。

标签: javascript node.js class asynchronous synchronous


【解决方案1】:

您会很快发现,所有异步操作在完成后必须能够与调用者通信,因为它们在未来某个不确定的时间完成。这意味着他们要么需要接受回调,要么需要返回一个承诺。

虽然可以将回调传递给构造函数,但不能从构造函数返回 Promise(它必须返回对象),因此通常不建议在构造函数中放置异步操作。相反,如果您构造对象然后在对象上调用异步方法,则调用者的代码流会更直接。

正如您的示例清楚地表明的那样,您没有为 User 对象的调用者创建任何方法来知道构造函数中的异步操作何时完成,因此,调用者没有可靠的方法来使用结果那个操作。这不仅是一个坏主意,而且完全不是首发。您将强制调用者设置某种超时,并且要么猜测异步操作何时完成,要么轮询寻找完成 - 都是不好的事情。

比较常见的设计方法是将异步操作分离成一个方法:

class User{
    constructor(){ }

    select(sql, callback) {
        Database.selectQuery(sql, this, function(data, obj){
            obj.name = data;
            callback();
        });
    }

} 

var x = new User();
x.select(statement, function() {
    console.log(x.name);
});

现在设计异步接口的现代方式确实正在转向 Promise,它们在错误处理和协调多个异步操作方面具有显着优势,因此这确实是我对接口的推荐。

您上面的界面可能还需要错误处理。

【讨论】:

  • 感谢您的回复。请忽略缺少错误处理 - 提供的代码已简化以有效地表达我的问题。为了进一步讨论,无论我创建异步构造函数还是单独的函数,我仍然有同样的问题。我必须将我的整个程序代码放在回调中。用户类应该是存储在服务器上的缓存版本,并将传递给视图。如果我使用回调,我看不到如何将它传递给视图。
  • @Andy - 欢迎使用 node.js 进行异步编程。是的,您必须将所有想要使用异步操作结果的代码放在完成回调或从那里调用的函数中。这就是异步编程在 Javascript 中的工作方式——时期。你需要习惯这个概念。您的设计可能需要调整,以便对象不会尝试使用异步操作初始化自身,因为该设计模式有问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-05
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 2020-03-29
相关资源
最近更新 更多