简体   繁体   English

Node.js:如何编写“异步” getter

[英]Node.js: How do I write an “asynchronous” getter

I'm new to Node.js, so apologies if my question sounds somehow stupid. 我是Node.js的新手,所以如果我的问题听起来有些愚蠢,请您道歉。

Here's what I'm heading for: 这就是我要去的地方:

I'm designing an object of which one property has to be set by database query. 我正在设计一个必须通过数据库查询设置其属性的对象。 For this task I'm requiring promise-mysql . 对于此任务,我需要promise-mysql In order to provide the property to other objects, I would like to have a getter that checks weather the property is set or not and in the latter loads the property from the database before returning its value. 为了将属性提供给其他对象,我希望有一个getter来检查天气是否设置了该属性,在后者中,后者将在返回值之前从数据库加载该属性。

My approach so far: 到目前为止,我的方法:

MyObject = function () 
{
    this._property = null;
};

MyObject.prototype._loadProperty = function() 
{
    var self = this;
    return pool.query('SELECT * FROM table WHERE condition = ?', [condition]).then(function(rows)
     {
         return self._property = rows;
     }).catch(function(err) 
     {
         console.log(err);
     });
 };

 MyObject.prototype._getProperty = function()
 {
     return this._property || this._loadProperty();
 }

So far the getter is returning a promise object if the property has not been set/loaded yet. 到目前为止,如果尚未设置/加载属性,则吸气剂将返回promise对象。 I can handle this promise object with ...then() in the calling function, but I would like the getter to hold back the return value until the promise has settled. 我可以在调用函数中使用... then()处理这个Promise对象,但是我希望getter保留返回值,直到Promise完成。 Is this even possible? 这有可能吗?

Regards Greg 问候格雷格

Your interface should probably just always return a promise. 您的界面可能应该总是返回一个承诺。 Then the caller can just do: 然后,调用方可以执行以下操作:

 this.getProperty().then(...)

Their interface will be the same whether the property was previously cached or not. 无论该属性先前是否已缓存,它们的接口都是相同的。


In fact, you can even use the promise internally as your caching mechanism. 实际上,您甚至可以在内部使用Promise作为缓存机制。

MyObject = function () {
    this._propertyPromise = null;
};

MyObject.prototype._loadProperty = function () {
    var self = this;
    return pool.query('SELECT * FROM table WHERE condition = ?', [condition]).catch(function (err) {
        console.log(err);
        throw err;             // propagate reject error back to caller
    });
};

MyObject.prototype.getProperty = function () {
    if (!this._propertyPromise) {
        this._propertyPromise = this._loadProperty();
    }
    return this._propertyPromise;
}

A reason for doing it this way is that you don't want the caller to have to know or do anything differently if the property is being fetched asynchronously or is already cached. 这样做的原因是,如果属性是异步获取的或已经缓存的,则您不希望调用方知道或执行其他操作。 The only way to offer the same interface for both is to make the interface always be async and just returning the promise gives you that automatically. 为两者提供相同接口的唯一方法是使接口始终保持异步状态,仅返回promise即可自动为您提供。

FYI, in the code you showed, you were using .catch() to log an error, but not rethrowing the error. 仅供参考,在您显示的代码中,您正在使用.catch()记录错误,但没有重新抛出该错误。 That would "silently" eat the error and it would not be returned back to the caller. 这将“无声地”吞噬错误,并且不会将其返回给调用方。 The caller would instead see a fulfilled promise with an undefined value. 呼叫者将改为看到带有undefined值的已兑现承诺。 If you want to do your own .catch() for logging reasons, then you must rethrow the error (or return a rejected promise) to make sure it propagates back to the caller. 如果出于日志记录的原因想要执行自己的.catch() ,则必须重新抛出错误(或返回被拒绝的承诺)以确保其传播回调用者。 A .catch() all by itself with no return value will just change the promise into a resolved promise because it assumes that you've handled the error. 本身没有返回值的.catch()只会将承诺更改为已解决的承诺,因为它假定您已处理了错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM