Асинхронный вызов на основе ответа от предыдущего вызова, избегая ада обратного вызова

1

Поэтому я обычно занимаюсь асинхронными функциями, используя цепочку .then. Но на этот раз он этого не решает. Это ситуация.

return Promise.all([
    Banner.findOne(),
    event.findOne({
        status: true
    }),
    Account.find({
        accType: 'employer'
    })
        .then(([banner, event, account]) => {
            res.render('index', {
                title: 'Web Project Studio',
                user: req.user,
                banner: banner,
                event: event,
                employer: account
            });
        }).catch(e => {
        console.error(e);
    })
]);

Так что это сработало, и все было здорово. Но теперь я решил изменить способ выбора активного event. Я вызываю коллекцию, называемую generalInfo и захватываю идентификатор к текущему событию. Вот что у меня есть до сих пор:

return Promise.all([
    Banner.findOne(),
    GeneralInfo.findOne(),
    Account.find({
        accType: 'employer'
    })
]).then(([banner, generalInfo, account]) => {
        Event.findById(generalInfo.activeEventId).then(r => {
            console.log('test');
            var event = r;
            res.render('index', {
                title: 'Web Project Studio',
                user: req.user,
                banner: banner,
                event: event,
                employer: account
            });
        }).catch(e => console.log(e));
    }
}).catch(e => {
    console.error(e);
})

Но этот код начинает выглядеть как аддон.

Я также пробовал что-то вроде этого:

var banner = await Banner.findOne().catch(e => console.log(e));
var currentEvent = await GeneralInfo.findOne().catch(e => console.log(e));
currentEvent.then(async r => {
    var event = await Event.findOneById(r.activeEventId).catch(e => console.log(e));
}).catch(e => console.log(e));

Это не завершено, но это как-то показывает мой образ мыслей. Но опять же, не повезло.

Итак, как я могу ладить с асинксом, не .then навсегда? Мне нужно передать все возвращенные объекты функции render.

  • 0
    Прежде чем опубликовать ответ, мне любопытно, захотите ли вы создать заметное из вашего обещания (или обещаний). Если это так, вы можете объединиться с map, concat и всеми этими замечательными наблюдаемыми операторами, которые позволяют вам делать подобные вещи процедурным (но, конечно, асинхронным) способом. Если вы не заинтересованы в rxjs, хотя я оставлю это.
  • 0
    Я понятия не имею, что это такое, но я все за любые ответы
Показать ещё 5 комментариев
Теги:
mongoose
asynchronous

2 ответа

2
Лучший ответ

Вы можете просто гнездиться раньше, что имеет преимущество перекрытия больше (см. *** комментарий (ы)):

return Promise.all([
    Banner.findOne(),
    GeneralInfo.findOne()
        .then(generalInfo => Event.findById(generalInfo.activeEventId)), // ***
    Account.find({
        accType: 'employer'
    })
}).then(([banner, event, account]) => {
    res.render('index', {
        title: 'Web Project Studio',
        user: req.user,
        banner: banner,
        event: event,
        employer: account
    });
}).catch(e => {
    console.error(e);
});

Если вы делаете это событие generalInfo => много, вы можете обернуть его в служебную функцию.

С другой стороны, если они не должны пересекаться, как это, вы можете свести к минимуму вложенности, добавив еще один, then:

return Promise.all([
    Banner.findOne(),
    GeneralInfo.findOne(),
    Account.find({
        accType: 'employer'
    })
]).then(([banner, generalInfo, account]) => {
    return Event.findById(generalInfo.activeEventId).then(event => { // ***
        return [banner, event, account];                             // ***
    });                                                              // ***
}).then(([banner, event, account]) => {
    res.render('index', {
        title: 'Web Project Studio',
        user: req.user,
        banner: banner,
        event: event,
        employer: account
    });
}).catch(e => {
    console.error(e);
})
2

Это должно сработать.

return Promise.all([
  Banner.findOne(),
  GeneralInfo.findOne(),
  Account.find({
    accType: 'employer'
  })
]).then(async ([banner, generalInfo, account]) => {
    res.render('index', {
      title: 'Web Project Studio',
      user: req.user,
      banner: banner,
      event: await Event.findById(generalInfo.activeEventId),
      employer: account
    });
}).catch(e => {
    console.error(e);
})

Ещё вопросы

Сообщество Overcoder
Наверх
Меню