想想Rails是如何让你定义一个属性与另一个属性相关联的:
class Customer < ActiveRecord::Base
has_many :orders
end
这不会为orders
设置数据库列,而是为orders
创建一个getter,这允许我们执行以下操作
@orders = @customer.orders
它将获取相关的orders
对象。
在JS中,我们可以很容易地用getter来实现这一点:
{
name: "John",
get orders() {
// get the order stuff here
}
}
但是Rails是 sync,而在JS中,如果在我们的例子中,我们要访问数据库,我们会做 async。
我们如何创建异步getter(和setter)?
我们会回报一个最终得到解决的承诺吗?
{
name: "John",
get orders() {
// create a promise
// pseudo-code for db and promise...
db.find("orders",{customer:"John"},function(err,data) {
promise.resolve(data);
});
return promise;
}
}
这样我们就可以
customer.orders.then(....);
或者我们可以更有Angular 地处理它,自动地将它解析为一个值?
总而言之,我们如何实现异步getter?
5条答案
按热度按时间vqlkdk9b1#
get
和set
函数关键字似乎与async
关键字不兼容,但是,由于async
/await
只是Promise
s的 Package 器,因此您可以只使用一个Promise
来使您的函数“await
-able”。Object.defineProperty
方法将async
函数赋给setter或getter。*吸气剂
承诺对吸气剂很有效。
这里,我使用Node.js 8内置的
util.promisify()
函数,它在一行中将节点样式的回调(“nodeback”)转换为Promise
,这使得编写支持await
的getter变得非常容易。设定器
对于二传手来说,这变得有点奇怪。
你当然可以把一个承诺作为一个参数传递给一个设定者,然后在里面做任何事情,不管你是否等待承诺的实现。
然而,我想象一个更有用的用例(就是我来到这里的那个用例!)是使用setter,然后
await
ing该操作在使用setter的任何上下文中完成。不幸的是,这是不可能的,因为setter函数的返回值被丢弃了。在本例中,
Done!
在1
秒后打印到控制台,Foo
在2
秒后打印。这是因为await
正在等待promisedValue
完成,它从未看到在setter内部使用/生成的Promise
。vbkedwbf2#
对于异步getter,您可以这样做:
相反,当遇到异步setter时,问题就出现了,因为表达式
a = b
总是产生b
,所以没有什么可以避免的,也就是说,对象中持有属性a
的setter不能覆盖这个行为。因为我也偶然发现了这个问题,所以我知道异步setter是不可能的,所以我意识到我必须选择一种替代设计来代替异步setter,然后我想出了下面的替代语法:
我用了下面的代码,
它返回异步属性的描述符,并给出另一个允许定义类似异步setter的描述符。
可以按如下方式使用上面的代码:
一旦你像上面那样设置了一个异步属性,你就可以像已经演示的那样设置它:
siotufzp3#
下面的代码允许代理处理程序中的异步设置器遵循Davide Cannizzo答案中的约定。
zzlelutf4#
下面是另一种方法,它创建了一个额外的 Package 器,但在其他方面它涵盖了我们所期望的内容,包括
await
的使用(这是TypeScript,只需去掉设置返回值类型的: Promise<..>
位以获得JS):wj8zmpe15#
下面是实现get orders函数的方法
您可以像这样调用此函数