【问题标题】:Do something after multiple async mongoose calls finishes在多个异步猫鼬调用完成后做某事
【发布时间】:2018-07-24 00:02:00
【问题描述】:

我有一个函数可以在几个不同的文档中查找数据,将每个文档中的一些日期添加到一个对象中,然后返回包含来自不同文档的组合数据的对象。唯一的问题是在任何事务完成之前返回对象。我用谷歌搜索了很多,我能找到的唯一解决方案是 Stack Overflow,但从 2012 年开始......必须有一些“更新”更好的方法吗? 最好不要安装更多的 npm 东西。

这是我的功能

function getPreviousEventCard(event, callback) {
    const card = {};
    card.dateStart = event.dateStart;
    card.dateEnd = event.dateEnd;
    card.userID = event.userID;
    card.adminID = event.adminID;

    // 1st async call
    Profile.getFullName(event.userID, (err, name) => {
        if (err) return callback(err, null);
        card.bsName = name.fullName;
    });

    // 2nd async call
    Profile.getProfileByUserId(event.parentID, (err, profile) => {
        if (err) return callback(err, null);
        card.parentName = profile.fullName;
        card.address = `${profile.address} ${profile.zip}`
    });

    // somehow wait until both(all) async calls are done and then:
    return callback(null, card);
}

顺便说一句,'Profile' 是一个猫鼬模式,get 方法使用 findOne() 方法。

我尝试嵌套函数并将返回回调作为最内部的,但由于某种原因它从未返回。

【问题讨论】:

  • 你用的是什么版本的Node?​​span>
  • Profile.getFullName 是否返回一个 Promise?如果是,您绝对应该使用异步等待
  • 您在 SO 上找到了什么内容,为什么您认为它不够好?你看过Promise.all()吗?我希望 getFullName()getProfileByUserId() 返回 Promises。
  • 将您的第二个异步调用放在第一个异步调用的回调中。然后第二个异步将在第一个完成之前不会运行。
  • 杰夫,我认为这不是一个好主意,然后我会在开始另一个 aync 调用之前等待......同时启动它们是最有效的,因为数据库独立于进行调用的 CPU。 @zero298 再也找不到它了……但对我来说似乎已经过时了。

标签: javascript node.js mongodb asynchronous mongoose


【解决方案1】:

如果您使用的是 NodeJS v8 或更高版本,我会 promisify 那些功能:

const getFullName = promisify(Profile.getFullName);
const getProfileByUserId = promisify(Profile.getProfileByUserId);

...然后使用Promise.all:

function getPreviousEventCard(event, callback) {
    Promise.all([
        // 1st async call
        getFullName(event.userID),
        // 2nd async call
        getProfileByUserId(event.parentID)
     ])
    .then(([name, profile]) => {
        const card = {
            dateStart: event.dateStart,
            dateEnd: event.dateEnd,
            userID: event.userID,
            adminID: event.adminID,
            bsName: name.fullName,
            parentName: profile.fullName,
            address: `${profile.address} ${profile.zip}`;
        };
        callback(null, card);
    })
    .catch(err => callback(err);
}

或者更好的是,让 getPreviousEventCard 返回一个承诺:

function getPreviousEventCard(event) {
    return Promise.all([
        // 1st async call
        getFullName(event.userID),
        // 2nd async call
        getProfileByUserId(event.parentID)
     ])
    .then(([name, profile]) => {
        return {
            dateStart: event.dateStart,
            dateEnd: event.dateEnd,
            userID: event.userID,
            adminID: event.adminID,
            bsName: name.fullName,
            parentName: profile.fullName,
            address: `${profile.address} ${profile.zip}`;
        };
    });
}

最好不要安装更多 npm 东西

如果您确实想要安装更多 npm 的东西,有一个 npm 模块将使用 API 函数的声明性描述来承诺整个 API(而不是逐个函数): https://www.npmjs.com/package/promisify

【讨论】:

  • @RasmusPuls:是的,第一句中的链接指向 Node 文档。它是在 v8 中添加的。
  • 这看起来很有用!谢谢,我会调查的。
  • @RasmusPuls:不用担心。仅供参考,我在上面添加了一些缺少的括号(我忘了把它们放在解构参数[name, profile] 周围),所以文字代码会有语法错误。 (你已经明白了,但是......)
猜你喜欢
  • 1970-01-01
  • 2017-02-22
  • 2020-10-27
  • 1970-01-01
  • 2015-11-03
  • 2014-12-14
  • 1970-01-01
  • 1970-01-01
  • 2019-01-22
相关资源
最近更新 更多