有没有更好的方法来处理 NodeJS 中的嵌套承诺? [英] Is there a better way to handle nested promises in NodeJS?

查看:58
本文介绍了有没有更好的方法来处理 NodeJS 中的嵌套承诺?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码看起来类似于:

I have code that looks something similar to:

const MyClass {
  checkExists: function(db_client) {
    return new Promise(fulfill, reject) {
      var sql = 'select * from table';
      db_client.connect().then(c => {
      }).then(res => {
        client.release();
        fulfill(res.rows[0].col1 === 1 ? true : false);
      }).catch(error => {
        reject(error);
      });
    });
  }
  doSomething: function(db_client) {
    return new Promise(fulfill, reject) {
      var sql = 'delete from table where x=1';
      db_client.connect().then(c => {     
      }).then(res => {
        fulfill();
      }).catch(error => {
        reject(error);
      });
    });
  }
};

module.exports = MyClass;

var myc = require('./MyClass.js');

myc.checkExists(db_client).then(resp => {
  if(resp === true) {
    myc.doSomething(db_client).then(resp => {
    console.log('success.');
  } else {
    console.log('we are done.');
  }
  }).catch(error => {
    console.log(error);
  });
}).catch(error => {
  console.log(error);
});

根据上面的示例,我必须运行一个依赖于另一个查询结果的查询.(为伪代码,如有错误请见谅)

Per the example above, I have to run a query that is dependent upon the result of another query. (It's pseudocode, forgive if I made mistakes)

但是,我注意到它开始导致嵌套的 Promise 或函数调用以及来自另一个 Promise 的实现中的 Promise.

However, I'm noticing that it starts to result in nested Promises or function calls with promises from within the fulfillment of another Promise.

我可以看到情况越来越糟.这是犹太洁食吗?有没有更好的方法来思考/处理我正在尝试做的事情?

I can see this getting worse and worse. Is this kosher? Is there a better way to think/handle what I'm trying to do?

不知道为什么它被标记为一个问题的副本,其中发布者似乎明确知道反模式并询问如何避免它与反模式/解决方案未知的问题发帖人,但认识到编程风格的问题并正在寻求帮助(其中讨论可能会产生相同类型的解决方案).

Not sure why it's being marked as a duplicate of a question where the poster seems to be explicitly aware of an anti-pattern and is asking how to avoid it vs. a question where the anti-pattern/solution is not known by the poster, but recognizes an issue in a programming style and is looking for help (in which the discussion may result in the same type of solution).

推荐答案

有没有更好的方法来处理 NodeJS 中的嵌套 promise?

Is there a better way to handle nested promises in NodeJS?

是的,有.您可以进行很多改进.您的伪代码似乎缺少一些部分,但我将展示我所能展示的最简单的版本,以捕捉您正在做的事情的精神:

Yes, there is. Lots of improvements you can make. Your pseudo-code seems to be missing some pieces to it, but I'll show the simplest version I can that captures the spirit of what it looks like you were doing:

const MyClass {
    checkExists: function(db_client) {
        var sql = 'select * from table';
        return db_client.connect().then(c => {
            // missing code here in your pseudo code
            // do something with c here to create the variable res
            client.release();
            // make this be the resolved value of the returned promise
            return res.rows[0].col1 === 1;
        });
    }
    doSomething: function(db_client) {
        var sql = 'delete from table where x=1';
        return db_client.connect().then(c => {
            // do something with c here
            // return value or another promise
        });
    }
  };

  module.exports = MyClass;

  var myc = require('./MyClass.js');

  myc.checkExists(db_client).then(resp => {
    if(resp === true) {
        return myc.doSomething(db_client).then(resp => {
            console.log('success.');
            // return something here to be the resolved value of the promise
            return resp;
        });
    } else {
        console.log('we are done.');
        // return something here to be the resolved value of the promise
        return resp;
    }
  }).catch(error => {
    console.log(error);
  });

以下是基本概念:

  1. 不要用手动创建的承诺包装现有的承诺.这被称为反模式,它没有任何好处,会膨胀您的代码,并且是错误处理错误的机会.只需返回您已有的承诺即可.

  1. Don't wrap an existing promise with a manually created promise. That's referred to as an anti-pattern and it provides no benefit, balloons your code and is an opportunity for error handling mistakes. Just return the promise you already have.

通过从 .then() 处理程序返回承诺,在 .then() 处理程序中链式嵌入承诺.

Chain embedded promises from within a .then() handler by returning the promise from the .then() handler.

您不需要在每个级别都.catch(),除非您明确需要在较低级别执行某些操作.被拒绝的承诺会自动沿链向上传播到下一个 .catch().这可以大大简化错误处理.

You don't need to .catch() at every level unless you explicitly need to do something at the lower level. Rejected promises will automatically propagate up the chain to the next .catch(). This can vastly simplify error handling.

如果您需要较低级别的 .catch(),即使只是为了记录目的,那么您必须 throw 来自 的错误.catch() 保持承诺被拒绝,否则拒绝将被视为已处理",链将切换到已解决.

If you need a .catch() at a lower level, even just for logging purposes, then you must throw an error from the .catch() to keep the promise rejected, otherwise the rejection will be considered "handled" and the chain will switch to resolved.

.then() 处理程序中,您有三个选项.您可以返回另一个承诺,它将被添加到链中.您可以返回一个值,它将成为父承诺链的已履行值.您可以抛出异常,当前链将被拒绝.如果不返回任何内容,则父承诺链的已履行值变为 undefined(就像一个不返回任何内容的函数).

In a .then() handler, you have three options. You can return another promise and it will be added into the chain. You can return a value and it will become the fulfilled value of the parent promise chain. You can throw an exception and the current chain will become rejected. If you return nothing, then the fulfilled value of the parent promise chain becomes undefined (just like a function that returns nothing).

仅供参考,这里有几篇关于 promise 反模式的文章,值得研究和付诸实践:

FYI, here are a couple articles on promise anti-patterns which are worth studying and putting into practice:

六种承诺反模式

延期和.then(success, fail) 反模式

关于您的代码的其他说明:

Other notes about your code:

  1. 在某些地方,您似乎缺少释放数据库连接的代码.

  1. In some places it looks like you're missing code to release a database connection.

在设计时,您应该非常清楚一个仅自行处理操作(包括错误)的函数,并且不期望调用者会处理错误,而不是一个函数来处理它的工作执行操作并返回结果或错误,以便调用者可以决定如何处理它们.这决定了您是否只是让被拒绝的承诺返回(供调用者处理),或者您是否必须在此处.catch() 对它们进行处理.

When designing, you should be very clear about a function that just handles an operation on its own (including errors) and there is no expectation that a caller will handler the error vs. a function whose job it is to carry out an operation and return the result or error so that caller can decide what to do with them. This determines whether you just let the rejected promises get returned (for the caller to deal with) or whether you have to .catch() them here and do something with them.

如果你 .catch() 清理或记录或类似的东西,但希望调用者仍然看到错误,你必须重新抛出错误以便承诺.catch() 运行后仍然被拒绝.

If you .catch() to clean up or log or something like that, but want the caller to still see the error, you have to re-throw the error so the promise stays rejected after your .catch() runs.

这篇关于有没有更好的方法来处理 NodeJS 中的嵌套承诺?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆