Javascript 基于前一个调用的响应的异步调用,避免了回调地狱

Javascript 基于前一个调用的响应的异步调用,避免了回调地狱,javascript,node.js,mongodb,asynchronous,mongoose,Javascript,Node.js,Mongodb,Asynchronous,Mongoose,因此,我通常使用.then链来处理异步函数。但这一次并不能解决问题。情况就是这样 return Promise.all([ Banner.findOne(), event.findOne({ status: true }), Account.find({ accType: 'employer' }) .then(([banner, event, account]) => { re

因此,我通常使用
.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);
    })
]);
这一切都很成功,一切都很好。但是现在我决定改变选择活动
事件的方式。我正在调用一个名为
generalInfo
的集合,并从那里获取当前事件的ID。以下是我目前掌握的情况:

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));
它还没有完成,但它显示了我的思维方式。但同样,没有运气


那么,我如何才能在不链接
的情况下与async相处呢?我需要将所有返回的对象传递给
render
函数。

您可以更早嵌套,这样做的优点是重叠更多(请参见
***
注释):

如果您经常使用generalInfo=>事件,您可能会将其包装在一个实用函数中

或者,如果它们不应该像那样重叠,您可以通过添加另一个
然后
来最小化嵌套:

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

您可以更早嵌套,这也有重叠更多的优点(请参见
***
注释):

如果您经常使用generalInfo=>事件,您可能会将其包装在一个实用函数中

或者,如果它们不应该像那样重叠,您可以通过添加另一个
然后
来最小化嵌套:

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);
})
这应该行得通

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);
})
这应该行得通

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

在我发布答案之前,我很好奇你是否愿意从你的承诺(或承诺)中创造一个可观察的结果。如果是这样的话,您可以将map、concat和所有这些伟大的可观察操作符合并在一起,它们可以让您以类似过程的方式(当然是异步的)完成这类工作。如果你对rxjs不感兴趣,尽管我不知道那是什么,但我完全支持任何答案。萨:你真的(真的!)需要查找“rxjs”并探索“可观察的”。基本上,它们允许您将数据表示为一个“流”,您可以将其与其他流合并,等待其他流准备就绪,等等。承诺对于它们所擅长的(几乎是即时一次执行)来说是好的,但是当您需要管理多个异步流时,特别是当它们需要按顺序管理、加入、重试等时,承诺在风格上开始崩溃。这需要一些努力,但是现在,如果你在做异步工作,你真的需要rxjs。无论如何,一个可观察的东西(代表异步数据流的东西)可以包装一个承诺,这样你就可以使用可观察的操作符等等。一定要查一下“rxjs中的多个流”,你会得到各种各样的教程和代码示例。谢谢在我发布答案之前,我很好奇你是否愿意从你的承诺(或承诺)中创造一个可观察的结果。如果是这样的话,您可以将map、concat和所有这些伟大的可观察操作符合并在一起,它们可以让您以类似过程的方式(当然是异步的)完成这类工作。如果你对rxjs不感兴趣,尽管我不知道那是什么,但我完全支持任何答案。萨:你真的(真的!)需要查找“rxjs”并探索“可观察的”。基本上,它们允许您将数据表示为一个“流”,您可以将其与其他流合并,等待其他流准备就绪,等等。承诺对于它们所擅长的(几乎是即时一次执行)来说是好的,但是当您需要管理多个异步流时,特别是当它们需要按顺序管理、加入、重试等时,承诺在风格上开始崩溃。这需要一些努力,但是现在,如果你在做异步工作,你真的需要rxjs。无论如何,一个可观察的东西(代表异步数据流的东西)可以包装一个承诺,这样你就可以使用可观察的操作符等等。一定要查一下“rxjs中的多个流”,你会得到各种各样的教程和代码示例。谢谢