0

I have the following function:

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

Then I have a function in which I have the following forEach loop:

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);

console.log for notifications returns me:

[ { _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> } } ]

My question is now how I can push the items (including the email) in my forEach loop when the Promised is resolved?

I tried it with

Promise.all(email).then(item => {
  item["supportMail"] = email; 
  notifications.push(item);
});

instead but this also did not work.

The important thing here is, that I want to access notifications outside the forEach loop. If I change the forEach to a async function, the console.log for notifications runs before the loop.

This is the whole JavaScript for reference: https://jsbin.com/gujiwatati/edit?js

2 Answers 2

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 also use 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);
    }
}));
Sign up to request clarification or add additional context in comments.

Comments

0

What your function installationService.getInstallationMail is returning is not a string as you might be expecting, what you are receiving is a promise cloudant.readDocument is returning. I suggest you to do something like the following:

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);
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.