What is the best way to encapsulate multiple Bluebird promises within a single promise?

Seeking assistance in creating an async wrapper for a redis query supported by a db query. If the redis query fails, I want to execute the db query instead. When the db query is successful, I aim to store the returned data in redis before sending it back. The function should ideally return a promise as it will be invoked within node.js. I am currently utilizing the bluebird promises library and using it to promisify redis. For the database, I am using mongo-gyro which is also based on bluebird. Both of these libraries work independently.

Any support would be highly valued - even if it's just pseudocode - particularly with error handling included.

function get_something(key){
redis.getAsync(key).then(function (res){
  if (null !== res){
    return Promise.resolve(res);
  }
})
.then(function (res){
  db.find({'_id:key'}).then(function (res){
    if (null !== res){
      redis.setAsync(key,result)
      .then(function(){
           return Promise.resolve(res);
      })
      .catch(...);
    return Promise.resolve(res);
    }
})
.catch(...);

};

Update: the following function works fine, with the final 'then' displaying data from redis or mongo. However, I have struggled to convert this into a method within a class that returns a promise to pass back to the node.js handler. Note that I had to add 'bind' to capture the source of the data

var oid = '+++++ test oid ++++++'
var odata = {
    'story': 'once upon a time'
}
var rkey = 'objects:'+ oid
redis.getAsync(rkey).bind(this).then(function(res){ 
  if(res === null){
    this.from = 'db'
    return db.findOne('objects',{'_id':oid}) 
  }  
  data = JSON.parse(res)
  this.from = 'redis'
  return data
})
.then(function(res){    
  if(res !== null && this.from == 'db'){
    data = JSON.stringify(res)
    redis.setAsync(rkey,data)
  } 
  return res
})
.then(function(res){ 
  console.log('result from ' + this.from)  
  console.log(res)                              
});

Answer №1

.done is used to end a promise chain. In most cases, Bluebird can detect unhandled rejections automatically.

If you're searching for the equivalent of .then, it's right here:

redis.get(key).then(function(res){
     // res represents Redis' .get response
     if(res === null) throw new Error("Invalid Result for key");
     return db.find({"_id":key); 
}).then(function(res){ 
     // res represents Redis' .find response
     return redis.set(key,result);
}).catch(function(k){
   if(k.message === "Invalid Result for key") {
       // handle no key found
   }
});

Answer №2

After reviewing your initial question and the subsequent update, it seems that achieving your goal does not necessarily require a flag to track the source of the data.

You can consider using the following approach:

function retrieveData(oid) {
    var key = 'objects:' + oid;
    return redis.getAsync(key).then(function(dataFromRedis) {
        if (dataFromRedis === null) {
            return Promise.cast(db.findOne('objects', {'_id': oid})).then(function(dataFromDb) {
                redis.setAsync(key, dataFromDb).fail(function() {
                    console.error('Failed to save ' + key + ' to redis');
                });
                return dataFromDb;
            });
        }
        return dataFromRedis;
    }).then(function (result) {
        if (result === null) {
            throw ('No value found for: ' + key);
        }
        return result;
    });
}

Additional Notes:

  • You may need to make adjustments to the code related to oid and key, as my knowledge in this area is limited.
  • The structure of the code might seem unconventional since the query on MongoDB is optional and the update on Redis is secondary to the main function's success.
  • The use of the Promise.cast() wrapper could potentially be unnecessary depending on the return value of db.findOne().
  • This implementation would greatly benefit from further refinement by someone well-versed in Bluebird.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on redirecting to a specific Vue-app page using Flask

I am currently working on an application that includes a page that ends with '@' and provides meta information for the page without '@'. For example, if the page '/user/aabb' contains information about the user 'aabb&apos ...

Utilize filters on a dataset to display specific information

Front-end: const [filters, setFilters] = useState({ type: "", country:"", }); const onChangeFilterType = e => { const workingObject = {...filters}; workingObject.type = e.target.value; setFilters(workingObject); }; ...

Building a custom onChange event handler in Formik allows for greater

I want to modify the onChange function in formik input so that it converts the value from a string to a number. However, I'm unable to change the behavior as expected and the console.log doesn't show up on the screen. It seems like Formik's ...

pdfMake introduces a page breaking effect when the canvas is utilized with the type "line"

Can anyone shed some light on why a canvas declaration with the type "line" is causing a page break in the generated PDF? I've tried removing all canvases and the page break disappears, but I can't identify the root cause. Any insights would be ...

having difficulty sending a post request with Angular

Submitting form data via HTTP post will look like this: saveDataFile(mutlidata,id,value): Observable<Response> { var _url = 'http://xxxx.xxx.xxx'; var saveDataURL = _url + '/' + id; var _this = this; ...

Dealing with multiple Datepicker components in React hooks

Managing a single instance of Datepicker in a React project is easy, but what about handling multiple instances? The date changes are not reflected on the UI even though they can be seen in the console. What are some efficient solutions to tackle this issu ...

What is the best way to handle waiting for an HTTP request to complete from a separate component?

https://i.sstatic.net/q4XYB.png An issue arises when calling the GetData function from a component's controller too early. I would like it to wait for the identification process to complete before triggering. During page loading, there is a server c ...

How can Angular be used for live search to provide precise search results even when the server does not return data in the expected sequence?

Currently, I am in the process of constructing a website for one of my clients. The search page on the site is designed to update search results as you type in the search bar - with each keystroke triggering a new search request. However, there's an i ...

Populating a span tag with data retrieved through Ajax

I encountered an issue with updating the totalDraftSalePrice HTML tag after a successful AJAX call. The data returned includes a field called SubtotalBasePrice, which I can visualize in JSON format, but for some reason, I am unable to update the HTML tag w ...

Removing sourceMappingURL from an Angular Universal build: A step-by-step guide

Using this repository as my foundation, I have successfully resolved most of the plugin errors except for one that continues to elude me. It's puzzling because no other plugin anticipates a .map file in an SSR build since it is intended for productio ...

Utilizing Selenium automation to navigate a website that features a custom jQuery plugin-checkbox functionality

Utilizing Selenium WebDriver along with JavaScript to automate the testing of a website that features a custom jquery plugin named "jcf" (JavaScript Custom Forms) for aesthetically pleasing forms. You can find more information about this plugin here. I am ...

Discover the most effective method of working with cached values in Django using Redis

Exploring the depths of Redis cache operations within Django has led me to ponder the efficiency of utilizing Redis methods directly. While Redis offers a variety of powerful operations, the native cache module in Django falls short in supporting them. I ...

Is there a way to set up gulp without relying on npm when using shared hosting?

While working on my shared hosting, I encountered a roadblock regarding the installation of gulp for compiling LESS assets into CSS. The hosting administrator has declined to install npm, which is essential for setting up gulp. Given this limitation, I am ...

Uploading a file to a .NET Framework API Controller using React

I am trying to figure out how to send files in the request body to an API controller in .NET framework using React. My goal is to achieve this without changing the request headers, so I want to send it as application/json. What I am looking for is somethi ...

Best Practices for Managing Asynchronous Updates in Angular Controllers

Let me explain my current setup -- I have a controller that utilizes a service to perform some tasks and then fetches data asynchronously. Right now, the data is returned after a timeout, but ideally it would involve more complex operations: This is how m ...

Missing callback pattern in NodeJS

When I spend hours writing NodeJS code, there's a common scenario that leaves me unsure of how to proceed. Take the following async function call (where we forget the necessary callback): function foo (callback) { // Perform a task and call callba ...

Target specifically the onhover div element using JQuery and trigger the smooth sliding down effect with the SlideDown() function

Is it possible to create a unique JQuery slidedown() function that will only be applied to the div where the mouse is hovering? I have managed to make it work by giving each div a separate class, but when I name them all the same, it triggers the slide do ...

Check out our website's event countdown timer featuring a server-sided event tracking system

Currently, I am in the process of developing a website and have the requirement to incorporate a timer on one of the pages. The goal is for the timer to count down from a specified time, such as DD::hh:mm 02:12:34, until it reaches zero. Once the countdown ...

Using yargs to pass parameters/arguments to a Node script through an npm script

Is it feasible to retrieve a key from yargs when utilizing as an npm script argument? A user inputs in the OSX terminal: npm run scaffold --name=blah which triggers in package.json: "scaffold" : "node ./scaffold/index.js -- " This leads to const yar ...

Guide on transmitting information to an API with Vue.js

Here is an example of my API call: this.$http.post("{{ route('shop.checkout.save-order') }}", {'_token': "{{ csrf_token() }}"}) .then(function (response) { if (response.data.success) { if (response.data.redirect_url) { windo ...