【问题标题】:Nesting .then() and catch in Javascript promise嵌套 .then() 并在 Javascript 承诺中捕获
【发布时间】:2021-02-25 16:15:57
【问题描述】:

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

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

【问题讨论】:

  • 一个快速的经验法则,所有的 Promise 都应该返回。即使您不这样做,它们也总是返回 Promise。

标签: node.js express sequelize.js


【解决方案1】:

您可以使用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()?
  • 使用then/catch 类似于使用async/await 作为两者都解决承诺,我个人尽量不使用then/catch,因为您遇到的问题,即嵌套。
  • 经过很好的搜索和学习,您的答案是最好的。
【解决方案2】:

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

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

这就是为什么,在这个sn-p中,我在开头声明了所有变量,以便保存所有值并在最终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));
};

【讨论】:

  • 谢谢!这是我需要知道和学习的。
猜你喜欢
  • 2019-01-08
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 2019-08-16
  • 2018-07-06
  • 1970-01-01
  • 2020-04-02
  • 1970-01-01
相关资源
最近更新 更多