Only add to the JavaScript array when the Promise has been successfully resolved

In my code, I have a function called installationService.getInstallationMail that retrieves a specific support email from a database.

installationService.getInstallationMail = (id) => {
  return cloudant.readDocument(dbInstallations, id)
    .then(installation => {
      return installation.supportMail;
    });
};

Additionally, there is a forEach loop in another function where I check certain properties and if conditions are met, I modify the items and push them to a notifications array:

properties.forEach(item => {
  if ((item.value > 0) && ((dateNow - item.value) > dateOneDay)) {
    let index = item._id.lastIndexOf("_");
    let result = item._id.substr(0, index);
    item["baseId"] = result;

    let email = installationService.getInstallationMail(item.baseId);
    item["supportMail"] = email;

    notifications.push(item);
  }
});
console.log(notifications);

When I log the notifications array after the loop, it shows that the supportMail property is still pending:

[ { _id: 'id_9oW9i8M9RU_CbT1mKOGPG',
    _rev: '26129-6dd842ab825bf291d876486b8157b07b',
    control: false,
    dataType: 1,
    maxValue: '100',
    measurable: true,
    minValue: '0',
    parentId: 'id_9oW9i8M9RU_eFyeP6BmdI',
    precision: 2,
    propertyType: 7,
    value: '1522907022112',
    baseId: 'id_9oW9i8M9RU',
    supportMail: Promise { <pending> } } ]

I tried using Promise.all inside the loop to wait for the promises to resolve before pushing the items to the notifications array, but it did not work as expected. The goal is to be able to access notifications outside of the forEach loop, but changing the loop to an async function causes the logging to happen prematurely.

If you want to see the full JavaScript code, you can find it here: https://jsbin.com/gujiwatati/edit?js

Answer №1

const notifications = [];
installationService.getInstallationMail = (id) => {
    return cloudant.readDocument(dbInstallations, id)
        .then(installation => {
            return installation.supportMail;
        });
};
Promise.all(properties.map((item) => {
    if ((item.value > 0) && ((dateNow - item.value) > dateOneDay)) {
        let index = item._id.lastIndexOf("_");
        let result = item._id.substr(0, index);
        item["baseId"] = result;
        let email = installationService.getInstallationMail(item.baseId);
        email.then((email) => {
            // update item after email resolves
            item["supportMail"] = email; 
        });
        notifications.push(item);
        // returm email Promise
        return email;
    }
})).then(() => { // wait for all pending email Promise's to finish
    console.log(notifications);
});

You can streamline this using the await/async syntax:

await Promise.all(properties.map(async (item) => {
    if ((item.value > 0) && ((dateNow - item.value) > dateOneDay)) {
        let index = item._id.lastIndexOf("_");
        let result = item._id.substr(0, index);
        item["baseId"] = result;
        let email = await installationService.getInstallationMail(item.baseId);
        item["supportMail"] = email;
        notifications.push(item);
    }
}));

Answer №2

It seems that the function installationService.getInstallationMail is not returning a string as expected. Instead, it is returning a promise from cloudant.readDocument. To resolve this issue, you can modify the code like this:

installationService.getInstallationMail = (id) => {
  let promise = Promise();
  cloudant.readDocument(dbInstallations, id)
    .then(installation => {
      promise.resolve(installation.supportMail);
      return;
    });
  return promise;
};
let emailPromise = installationService.getInstallationMail(item.baseId);
emailPromise.then(email => {
  item["supportMail"] = email;
  notifications.push(item);
  console.log(item);
})

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

A step-by-step guide on incorporating a div panel in HTML and JavaScript triggered by a submit button click within an HTML form

For the past 3 to 4 days, I've been grappling with an issue. I've put together a student registration form using HTML and JavaScript. The form includes validation through JavaScript and string concatenation to submit all form values and display s ...

Unable to open javascript dialog box

One issue I encountered involves a jqGrid where users have to click a button in order to apply any row edits. This button is supposed to trigger a dialog box, which will then initiate an ajax call based on the selected option. The problem lies in the fact ...

A function in Typescript that returns an array of strings

I am experiencing an issue where my console statement is not displaying the length of the string array. Oddly enough, when I print 'list' within the for loop, it does show data. public getText = (items: any) => { let list: string[] = []; ...

Add delayed event listeners to embedded AJAX request beyond function boundaries

I'm working on developing a custom AJAX method extension named getApi that automatically includes my authentication bearer token in the request header. In my code, there is a function called getToken() which retrieves the token either from sessionSto ...

Deciding on the Best Placement for Hooks in FeathersJS

Initially, I had a function that performed three different tasks and everything was fine. In an attempt to enhance reusability, I decided to split these tasks into three independent hooks. Here is how they look: module.exports = function(options = {}) { ...

Refreshing Values in a Set of Organized Data

My current task involves creating a leaderboard program. Unfortunately, only 4 out of the 6 main functions are working properly: fillplayer, addplayer, and displaystats. I'm struggling with understanding how to update scores within a structure and sor ...

Retrieve the JS function within a return statement

Is there a way to call the showDashboard and showTimeline functions using the $(...) function in the code snippet below? define(["jquery", "bootstrap", "./timeline"], function($, bootstrap, timeline) { $(function(){ $("#right-menu-dashboard").clic ...

Is there a way to automate clicking on a hyperlink?

Is it possible to automatically play the top video in a lightbox after using AJAX to get the videos list and viewing it? ...

Using the logical operator || will yield a numeric result rather than a boolean value

Here's an example with two if conditions. The first if condition functions correctly, but the second if condition returns 11 unexpectedly. It's clear that the second if condition is incorrect, but it's worth exploring why JavaScript outputs ...

What is the best way to generate an array containing object reference variables?

While developing a Java program, I encountered an issue where I kept getting the error "Exception in thread "main" java.lang.NullPointerException" whenever I tried to run it. After some investigation, I realized that this error was due to an array of Refer ...

Performing a JavaScript array calculation on data retrieved from a database

Can someone help me with automatically calculating values using the onchange event in text boxes? I need to calculate the total based on input from an array in a database using the onchange event. HTML : <td class="text-left"><input type="text ...

Utilizing a nested interface in Typescript allows for creating more complex and

My current interface is structured like this: export interface Foo { data?: Foo; bar?: boolean; } Depending on the scenario, data is used as foo.data.bar or foo.bar. However, when implementing the above interface, I encounter the error message: Prope ...

Encountering a "Image is undefined" error in Node.js when attempting to read a property

As I attempted to create a shopping cart, I found myself working on an admin panel where I needed to upload images for adding products. After setting up the form <section> <div class="container mt-4"> <div class="row" ...

What is the best way to add a bootstrap file to my ejs templates?

I recently installed bootstrap using npm with the command 'npm -bootstrap@3'. However, when attempting to include the bootstrap.min.css file from node_modules in my application, I encountered an error message on my console. Here is a screenshot o ...

"Adding a pipe separator to a list of strings in Python: A step-by-step

In my Python code, I am working with an array of strings. I have a loop that iterates through each value and attempts to add a ('|') symbol using the code below. However, it is not adding the symbol as expected. result_list = [] new_value = &apo ...

The WebView.HitTestResult method is currently only receiving <img src> elements and not <a href> elements

I am attempting to open a new window in the Android browser using "_blank". I have set up an event listener for this purpose. mWebView.getSettings().setSupportMultipleWindows(true); mWebView.setWebChromeClient(new WebChromeClient() { ...

What is the best way to transform a for loop using array.slice into a for-of loop or map function in order to generate columns and rows

Experiencing an issue with Angular8. Seeking help to convert a for loop for an array into a loop utilizing either for-of or array.map. The code in question involves passing an array of objects and the need to separate it into col and row arrays for visual ...

Incorporate live data into a sample chart.js file within a Django template

I'm currently using the "start bootstrap4" template in my Django project. I need to customize the data displayed in a chart contained within the template by modifying the chart-pie-demo.js file. In my views.py file, I have defined the data that I wan ...

Polymorph 1.0 - Using CSS Class Binding for Dynamic Properties

I attempted to link a CSS Class to a paper-progress element using the value of my property to change the item's color. I referenced Polymer's example on GitHub and studied the documentation on Data-binding. Here is my code: http://jsbin.com/bide ...

The unexpected blank space appearing beneath my website as a result of images and videos placed on the

There seems to be some random white space on my website between the main body elements and the footer. Interestingly, removing the cat image and videoplayer eliminates this white space. However, I don't want to remove them completely, so I'm tryi ...