NODE JS: Как я могу заставить следующий вызов ждать, пока вызываемая функция завершит sh, прежде чем продолжить - PullRequest
0 голосов
/ 07 мая 2020
• 1000 в следующем файле:
c.on('drain', async function () {
    Database.addDataToDb(ArticleList);
    console.log("All done");
});

ВОПРОС: Как сделать так, чтобы console.log("All done") отображал сообщение только после того, как Database.addDataToDb(ArticleList) завершил выполнение?

Ответы [ 3 ]

3 голосов
/ 07 мая 2020

Это решение довольно беспорядочно, потому что у вас есть большая смесь асинхронных методов, смешанных в одной функции: события, обещания и обратные вызовы, а кроме того, есть al oop. Это действительно беспорядок, и обычно этого следует избегать. шаги выше, чем это. Для своей базы данных вы должны go найти и использовать интерфейс обещания к базе данных. Для ваших событий, поскольку это одноразовые события, вы можете создать оболочку обещания для объекта, чтобы получать уведомления об открытии и событиях ошибки.

Но, поскольку я не знаю всех компонентов, которые вы ' при использовании я не могу сделать эту часть за вас. Итак, мы рассмотрим, что мы могли бы сделать, чтобы исправить соответствующую поддержку на уровне обещаний в этой комбинации методов.

const {promisify} = require('util');

function addDataToDb(articleData) {
    return new Promise((resolve, reject) => {
        initMongoDb();

        kanpionDb.on('error', err => {
            console.error('connection error:', error);
            reject(error);
        });
        kanpionDb.once('open', function () {
            SiteUrlModel.init().then(() => {
                return Promise.all(articleData.map(articleItem => {
                    let model = new SiteUrlModel(articleItem);
                    model.savePromise = promisify(model.save);
                    return model.savePromise().then(() => {
                        console.log("Success " + articleItem.siteName);
                    }).catch(err => {
                        console.log("Failed: " + articleItem.siteName);
                        throw err;
                    });
                }));
            }).then(resolve, reject);
        });
    });
}

// usage:
addDataToDb(articleData).then(() => {
    console.log("All Done");
}).catch(err => {
    console.log(err);
});

Сводка методов:

  1. Из-за события, нам придется заключить в созданное вручную обещание, которое мы разрешим или отклоним, когда закончим.
  2. .forEach() l oop заменяется на Promise.all(articleData.map(...)), что даст нам обещание, которое сообщает нам, когда все сохранения выполнены.
  3. .save(callback) необходимо заменить на обещанную версию .save(). В идеале вы должны просто использовать здесь обещанную версию интерфейса вашей базы данных, но я показал, как вручную назначить функцию .save(), если это необходимо.
  4. Отклонение подключения к событию error.
  5. Принять решение и отклонить обещание SiteUrlModel.init().
  6. Связать обещание Promise.all() с обещанием SiteUrlModel.init().
0 голосов
/ 07 мая 2020

Вы можете использовать обещания, чтобы вызывающий абонент ждал, пока ваш асинхронный c код завершится sh. Реорганизуйте вашу функцию addDataToDb, чтобы вернуть обещание и соответственно разрешить / отклонить обещание. Поскольку вы определили обратный вызов "слив" как функцию asyn c, вы можете использовать ключевое слово await внутри обратного вызова, чтобы сделать его немного более лаконичным:

c.on('drain', async function () {
    await Database.addDataToDb(ArticleList);
    console.log("All done");
});
0 голосов
/ 07 мая 2020

, пожалуйста, попробуйте это,

const saveData = (articleItem) => {
  return new Promise((resolve, reject) => {
     var article = new SiteUrlModel(articleItem).save(function (error) {
        if (error) {
           console.log("Failed: " + articleItem.siteName);
           reject(error);
        } else {
           console.log("Success " + articleItem.siteName);
           resolve('Success');
        }
     });
  });
});

const addDataToDb = (articleData) => {
  const list = [];
  return new Promise((resolve, reject) => {
    initMongoDb();

    kanpionDb.on('error', console.error.bind(console, 'connection error:'));
    kanpionDb.once('open', function () {
      SiteUrlModel.init().then(() => {
        articleData.forEach(articleItem => {
          list.push(saveData(articleItem);
        });
      });
    });

    Promise.all(list).then(response => {
      resolve(response);
    }).catch(error => {
      reject(error);
    })
  });
};

c.on('drain', async function () {
  const result = Database.addDataToDb(ArticleList).then(res => {
    console.log("All done");
  });
});

Я пытаюсь использовать ванильные обещания

...