简体   繁体   中英

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

I'm new to Node.js, so apologies if my question sounds somehow stupid.

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 . 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.

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. 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. 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.

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.

FYI, in the code you showed, you were using .catch() to log an error, but not rethrowing the error. 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. 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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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