JS Array.push только после разрешения Promise - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть следующая функция:

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

Тогда у меня есть функция, в которой у меня есть следующий цикл forEach:

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 для уведомлений возвращает меня:

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

Теперь у меня вопрос, как я могу вставить элементы (включая электронную почту) в цикл forEach, когда Обещанное разрешено?

Я попробовал это с

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

вместо этого, но это также не сработало.

Здесь важно то, что я хочу получить доступ к notifications вне цикла forEach. Если я изменю forEach на асинхронную функцию, console.log для notifications будет запущен перед циклом.

Это весь JavaScript для справки: https://jsbin.com/gujiwatati/edit?js

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018
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);
});

Вы также можете использовать await/async синтаксис

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);
    }
}));
0 голосов
/ 06 ноября 2018

То, что возвращает ваша функция installationService.getInstallationMail, - это не строка, как вы могли бы ожидать, а то, что вы получаете, - это обещание cloudant.readDocument. Я предлагаю вам сделать что-то вроде следующего:

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);
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...