Node.js Wait for callback or database response

1.2k Views Asked by At

I have seen lots of very similar questions but don't give a direct answer for actually waiting. I have a script based on Bookshelf.js;

var Product = bookshelf.Model.extend({
  tableName: 'amazon_products',
  hasTimestamps: true,
  virtuals: { //https://github.com/bookshelf/bookshelf/wiki/Plugin:-Virtuals
    hasSiteProduct: function() {
      var product_references = this.related('siteProductsReferences').fetch()
      return product_references.length;
    }
  }

});

I have setup a virtual property that will simply count the OneToMany relations of the model and return the count. But in this case it looks like this.related('siteProductsReferences').fetch() has to take sometime before returning a response. The this.related('siteProductsReferences').fetch() also has a promise that can look like this;

this.related('siteProductsReferences').fetch().then(function(result) {
  // ...
});

I am building this to be returned via an API. If I just add return this.related('siteProductsReferences').fetch() to the method I get a full l get;

,"hasSiteProduct":{"isFulfilled":false,"isRejected":false}

So clearly the callback has not finished.

1

There are 1 best solutions below

1
On BEST ANSWER

Because the database operation returns a promise, your function also needs to return a promise - there's no getting out of that, you have to pass the promise back to the caller which will need to .then() it.

Below does not work because you cannot access .length on a promise that has not been fulfilled yet:

hasSiteProduct: function() {
    var product_references = this.related('siteProductsReferences').fetch()
    return product_references.length;
}

However you can do this:

hasSiteProduct: function() {
    var product_references_length_promise = 
    this.related('siteProductsReferences').fetch()
    .then(product_references => {
        return product_references.length;
    })

    // return the promise - it has not completed yet, client must .then() it
    return product_references_length_promise; 
}

the client needs to .then() the promise returned like so:

hasSiteProduct().then(num_product_references => {
    // do something with num_product_references 
})

For what it's worth I think you may be going down the wrong path in building an in-memory model of your data. This has been a technique favored by Object Oriented developers when dealing with data from a database, but I've always found very hard to make this work in an elegant way - it takes a lot of effort to build the model and the effort doesn't really pay off.