嵌套 .then() 并捕获 Javascript promise

Nesting .then() and catch in Javascript promise

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

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

您可以使用 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 次调用,因为这会影响您的性能。

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

如果您通过管道传输多个 .then(),您可以 return 一个值作为它们每个的承诺,一旦承诺解决,就可以在下一个中使用。唯一的问题是你丢失了这些值,除非你用新属性将它们保存在 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));
};