Steps to extract a value from a Promise

I've encountered some challenges with Promises and I'm curious to delve deeper into how they operate. In my current project, I'm utilizing the Bookshelfjs ORM to retrieve data from Postgres.

The code snippet below represents my current focus. For this request, I receive an array of device IDs, each corresponding to a device operating in one of two modes.

router.post('/devices', function (req, res, next) {
var currentData = [];
var deviceIds = req.body.devices;
loadash.forEach(deviceIds, function (device) {
    var deviceid = device.deviceid;
    Device.forge()
        .where({deviceid: deviceid})
        .fetch({columns: ['id', 'mode']})
        .then(function (fetchedDevice) {
            if(fetchedDevice.get('mode') === 1) {
                Model_1.forge()
                    .where({device_id: fetchedDevice.get('id')})
                    .orderBy('epoch_time', 'DESC')
                    .fetch()
                    .then(function (modelOne) {

                        //first push
                        currentData.push(modelOne.toJSON()); 

                        //array with first push data                
                        console.log(currentData)                                    
                    })
                    .catch(function (err) {
                        console.log(err);
                    });
            }
            else if(fetchedDevice.get('mode') === 2) {
                Model_2.forge()
                    .where({device_id: fetchedDevice.get('id')})
                    .orderBy('epoch_time', 'DESC')
                    .fetch()
                    .then(function (modelTwo) {

                        //second push
                        currentData.push(modelTwo.toJSON());

                        //array not empty here(shows data from both push)                
                        console.log(currentData);                                   
                    })
                    .catch(function (err) {
                        console.log(err);
                    });
            }
        })
        .catch(function (err) {
            console.log(err);
        });
   });
//This shows an empty array
console.log('Final: ' +currentData);                                                           
});

Asynchronous behavior in Javascript is likely causing the issue that results in an empty array being displayed. My questions are:

  1. How can I display the final array after all push() operations have been completed? I attempted using the Promise.all() method without success.

  2. Is it feasible to extract modelOne or modelTwo from each promise and then add them to an array? How can I achieve this?

Answer №1

It's best to avoid nesting then statements and instead try to keep the promise chain flat for better readability and maintainability. Additionally, consider combining similar model cases into a single block of code to follow the DRY principle. When working with arrays of promises, utilize map over forEach so you can easily pass them to Promise.all:

router.post('/devices', function (req, res, next) {
    var promises = lodash.map(req.body.devices, function (device) {
        return Device.forge()
            .where({deviceid: device.deviceid})
            .fetch({columns: ['id', 'mode']})
            .then(function (fetchedDevice) {
                var model = [Model_1, Model_2][fetchedDevice.get('mode')-1];
                if (model) {
                    return model.forge()
                        .where({device_id: fetchedDevice.get('id')})
                        .orderBy('epoch_time', 'DESC')
                        .fetch();
                }
            }).catch(function (err) {
                console.log(err);
            });
       });
    Promise.all(promises).then(function (currentData) {
        currentData = currentData.filter(model => model) // exclude undefined
            .map(model => model.toJSON());
        console.log('Final: ' +currentData); 
    });
}

Answer №2

Utilize the .map() function alongside Promise.all(), enabling you to return a value from a function passed to .then().

var currentData = loadash.map(deviceIds, function (device) {
    var deviceid = device.deviceid;
    return Device.forge()
        .where({deviceid: deviceid})
        .fetch({columns: ['id', 'mode']})
        .then(function (fetchedDevice) {
            if(fetchedDevice.get('mode') === 1) {
                // Obtain value from `.then()`
                return Model_1.forge()
                    .where({device_id: fetchedDevice.get('id')})
                    .orderBy('epoch_time', 'DESC')
                    .fetch()
                    .then(function (modelOne) {
                        // Obtain value from `.then()`
                        return modelOne.toJSON(); 

                    })
                    .catch(function (err) {
                        console.log(err);
                    });
            }
            else if(fetchedDevice.get('mode') === 2) {
                // Obtain value from `.then()`
                return Model_2.forge()
                    .where({device_id: fetchedDevice.get('id')})
                    .orderBy('epoch_time', 'DESC')
                    .fetch()
                    .then(function (modelTwo) {
                        // Obtain value from `.then()`
                        return modelTwo.toJSON();

                    })
            }
        })

   });

   var res = Promise.all(currentData);
   res
   .then(function(results) {console.log(results)})
   .catch(function (err) {
     console.log(err);
   });

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

Issue with Node Canvas/Resemble.js: The image provided has not finished loading during the load operation

Recently, I encountered a challenge while trying to utilize Resemble.js in a node environment. Despite some initial complications with installing canvas/cairo due to OS X Mavericks/XQuarts and Homebrew issues, I eventually succeeded. After making signific ...

What is the best way to use createElement in JavaScript to insert <p> and <span> elements within a <div>?

I am currently experimenting with generating sentences accompanied by draggable text boxes. To achieve this, I intend to construct the following HTML structure using JavaScript exclusively: <div> <p>Data1<span class = "smallBox droppabl ...

Utilize JavaScript or jQuery to segment HTML elements

Looking for a front-end solution to a common practice. In the past, I've stored reusable HTML elements (such as <nav>, <header>, <footer>, etc.) in a functions.php file and used PHP functions to include them on multiple pages. This ...

Instructions on how to navigate to a class page by clicking a button in a ReactJS interface

I am currently working with React and have implemented 3 classes in separate files. The App.js file contains a navbar and button, which when clicked, displays a table from 'Table.js'. I have also added buttons in front of each row in the table th ...

Contrast 2 GET objects retrieved from separate controllers

I have 2 collections of data from different controllers. Data Collection 1 (Controller Name): [{id:1,"name":"jakov"},...] Data Collection 2 (Controller Nickname): [{id:1, "nickname" : "jandric", "nameId" :1, "title" : "master"},...] I send data from C ...

Need help with fixing the problem in my side menu bar and making the content scroll smoothly

Check out my code on JS Fiddle here: http://jsfiddle.net/kodi/d2s3uja0/1/ I'm having trouble getting my side menu bar fixed and the content to scroll. I want to display the menu vertically on the left just like this: M E N U Any suggestions on how ...

Modify the database entry only if the user manually changes it, or temporarily pause specific subscriptions if the value is altered programmatically

After a change in the viewmodel, I want to immediately update the value on the server. class OrderLine { itemCode: KnockoutObservable<string>; itemName: KnockoutObservable<string>; constructor(code: string, name: string) { ...

When invoking a function using ng-init within ng-repeat, only the final item in the iteration yields a result

My goal is to update the content of a progress bar for each row in a table using ng-init within ng-repeat. Here is my code snippet: The code snippet for the view section is as follows: <tr ng-repeat-start="p in projetsListe" ng-init={{progressBar($in ...

Having trouble getting my javascript integration to work in a Django template - any ideas on what could be causing

As a newcomer to Django, I'm working on creating a small webpage that displays a chart using Chart.js. My goal is to load the JavaScript file statically. To achieve this, I have set up a basic HTML file named data_table.html and included a "static" fo ...

Exploring ways to repeatedly collapse rows using HTML, CSS, and JavaScript

GOAL: I want to freeze the header, freeze the first column, and be able to collapse rows multiple times. CURRENT PROGRESS: I have achieved freezing the header, first column, but can only collapse rows once. MY CODE SNIPPET: </head> <body> &l ...

Acquiring the index of a selector event within a list of dynamic elements

I am seeking guidance on how to go about solving the issue of obtaining an event index. I have a hunch that closures might play a role in the solution and would appreciate some insights. Initially, I dynamically build an HTML5 video container using an aja ...

Displaying information from an array using AngularJS

I'm struggling to display data from an array and I could use some help. Here's a snippet from my service.js file: this.fetchData = function() { var myArray = $resource('url', {method: 'get', isArray: true}); myArray ...

Module for Npm that includes unique code for both proxy support and non-proxy support configurations

Is there a way to develop a javascript library (available as a module on npm) with multiple implementations based on the level of proxy support in the environment where it is executed (transpiled to)? From my understanding, babel may not easily transpile ...

Is there a way to use JavaScript to choose options within a <select> element without deselecting options that are disabled?

Here's the code snippet I am working with at the moment: <select id="idsite" name="sites-list" size="10" multiple style="width:100px;"> <option value="1" disabled>SITE</option> ...

The Google Apps Script is currently showing the incorrect date as 3/1/2020 instead of today's date which is 4/6/2020

function findCorrectDate(){ currentDate = new Date(); currentDay = currentDate.getDay(); currentMonth = currentDate.getMonth(); currentYear = currentDate.getFullYear(); Logger.log(currentMonth, currentDay, currentYear); } Can anyone explain why ...

When I delete the initial element from the array, the thumbnail image disappears

Using react-dropzone, I am attempting to implement image drag and drop functionality. The dropped image is stored in the React state within a files array. However, a problem arises when removing an image from the array causing the thumbnails of the remain ...

What is the process for uploading images using Node.js with Express.js and MongoDB?

I'm currently using Mongoose and looking to enable users to upload their profile pictures. Is there a straightforward method to accomplish this task? ...

Discovering and choosing the appropriate course

I am facing a situation where I need to specifically select an element with the class .foo, but there are two anchor tags, both having the class .foo. However, I only want to select the one without the additional .bar class. How can I achieve this? <a ...

Performing a JSON AJAX call that sends a null object to a Java class

Within my JavaScript file, I am utilizing the following getJSON method like so: $.getJSON('do/ajax-convertlocaldatetime', { timestamp : localdatetime, The localdatetime variable is an instance of a LocalDateTime object. This ajax call trigg ...

In JavaScript, what is the best way to target the initial option element in HTML?

As a newcomer to javascript, I'm wondering how to target the first option in the HTML <option value="">Choose an image...</option> without altering the HTML itself? My thought is: memeForm.getElementById('meme-image').getElement ...