嵌套 .then() 并捕获 Javascript 承诺

时间:2021-02-18 18:04:08

标签: node.js express sequelize.js

我对 Javascript 承诺没有经验,最近我开始在我的 Javascript 项目中使用承诺而不是回调。
当我试图一个接一个地运行几个 promise 函数时,我陷入了 then() 的嵌套混乱中。代码完全按预期工作,但我的问题是,如果这是一个接一个地解决多个承诺函数的方法,那么使用承诺而不是回调的优势是什么。
如果我没有以正确的方式做这件事,那么这是你们要求向我展示解决嵌套承诺的正确方法。 以下是我不喜欢的代码,它们的外观如下:

exports.editExpense = (req, res, next) => {
    Account.findAll().then(accounts => {
        Budget.findAll().then(budgets => {
            Expense.findAll().then(expenses => {
                Expense.findByPk(id).then(expense => {
                    res.render('expenses/index', {
                        urlQuery: urlQuery,
                        expenses: expenses,
                        expense: expense,
                        accounts: accounts,
                        budgets: budgets
                    });
                })
            })
        })
    }).catch(error => console.log(error));
};

2 个答案:

答案 0 :(得分:3)

您可以使用 async/await 结构以获得更好的格式

exports.editExpense = async(req, res, next) => {
    try {
      let accounts = await Account.findAll();
      let budgets = await Budget.findAll();
      let expenses = await Expense.findAll()
      let expense = await Expense.findByPk(id);
      if (expense) {
        res.render('expenses/index', {
          urlQuery: urlQuery,
          expenses: expenses,
          expense: expense,
          accounts: accounts,
          budgets: budgets
        });
      } else {
        console.log('else') //<<- Render/Handle else condition otherwise server will hang.
      }
    } catch (error) {
      console.error(error)
    }

您应该尽量减少在函数中进行的 async 调用数量,因为它会影响您的性能。

答案 1 :(得分:3)

如果您更喜欢使用 then catch 结构,为了充分利用它,我建议您不要嵌套它们。当然可以,但是您应该在每个之后加上 .catch()。这就是 async 介绍使代码更易于阅读和处理错误的原因,因为它使用 try catch 结构简化了代码。

如果您通过管道传输多个 .then(),您可以从每个 req 返回一个值作为承诺,一旦承诺解决,就可以在下一个中使用该值。唯一的问题是您会丢失这些值,除非您将它们保存在具有新属性的 .then() 中或在 res 管道外声明的变量中。

这就是为什么在这个片段中,我在开头声明了所有变量,以便保存所有值并在最后的 exports.editExpense = (req, res, next) => { let accounts; let budgets; let expenses; Account.findAll() .then(fetchedAccounts => { accounts = fetchedAccounts; return Budget.findAll() }) .then(fetchedBudgets => { budgets = fetchedBudgets; return Expense.findAll() }) .then(fetchedExpenses => { expenses = fetchedExpenses return Expense.findByPk(id) }) .then(expense => { return res.render('expenses/index', { urlQuery: urlQuery, expenses: expenses, expense: expense, accounts: accounts, budgets: budgets }); }) .catch(error => console.log(error)); };

def compared_with_top(self):
    top = Pizza.objects.exclude(pk=self.pk).annotate(
        tcount=Count('on_pizza')
    ).order_by('-tcount')
    pizzas = Pizza.objects.filter(pk=self.pk).annotate(
        tcount=Count('on_pizza')
    ).union(top[:3])