【问题标题】:NodeJS Promise behaviour queryNodeJS Promise 行为查询
【发布时间】:2015-04-21 07:28:59
【问题描述】:

我在 nodejs 中试验 Promise 以更好地理解它是如何工作的。我有部分工作代码,但我不确定我是否正确使用它。我的意图是将错误或正确结果传递回调用者函数。所有这些回调似乎使这变得复杂。这是我目前所拥有的。

//This is my main CALLER function
function query_mcafee_mssql_type(database, node_name, type) {
  return new Promise(function (fulfill, reject) {
    switch (type) {
      case "currentDefinitionDate":
          computeCurrentDefinitionResult(database, node_name)
          .then(function (result) {
            console.log('query_mcafee_mssql_type' + result);
            fulfill(result);
          });
          break;
    }
  });
}

function computeCurrentDefinitionResult(database, node_name) {

  return new Promise(function (fulfill, reject) {
    var leaf_sql_query = "SELECT * FROM "+  JSON.stringify(database)  +".dbo.EPOLeafNode WHERE NodeName=" + "'" + node_name + "'";
    query_mcafee_mssql(leaf_sql_query)
    .then(function (LeafNode) {
         if (LeafNode == undefined) {
          fulfill(LeafNode);
         } else {
          return LeafNode;
         }
    })
    .then(function (LeafNode) {
      console.log('computeCurrentDefinitionResult' + LeafNode);
      var product_properties_sql_query = "SELECT * FROM "+  JSON.stringify(database)  +".dbo.EPOProductProperties WHERE ParentID=" + "'" + LeafNode.AutoID + "'" + "AND ProductCode LIKE 'VIRUSCAN%'";
      return query_mcafee_mssql(product_properties_sql_query);
    })
    .then(function (ProductProperty) {
      if (ProductProperty == undefined) {
          fulfill(ProductProperty);
      } else {
          return ProductProperty;
      }
    })
    .then(function (ProductProperty) {
      fulfill(ProductProperty.DATDate);
    });
  });
}

function query_mcafee_mssql(sql_string) {
  return new Promise(function (fulfill, reject) {
    query_mssql(mcafee_config, sql_string)
    .then(function (sql_response) {
      fulfill(sql_response);
      console.log('query_mcafee' + sql_response);
    });
  });
}

function query_mssql(config, sql_string){
  return new Promise(function (fulfill, reject) {
    var connection = new sql.Connection(config, function(err) {
      // ... error checks 
      if (err) {
        console.log('connection to mssql has failed');
        //throw err;
        fulfill();
      } else {
        // Query 
        var request = new sql.Request(connection); 
        request.query(sql_string, function(err, recordset) {
          // ... error checks should go here :
          if (err) {
            console.log('requst query error');
            fulfill();
          } else {
            // output query result to console:
            //console.log(recordset);
            fulfill(recordset);
         }
        });
      } 
    });
  });
}

我的主要调用函数是 query_mcafee_mssql_type()。我使用 Promise 来允许执行查询。一旦完成,如果它是一个错误,我希望“未定义”返回其他正确的结果返回给调用者。

据我了解,履行和拒绝回调决定了 Promise 的命运。 调用堆栈中最顶层的是函数 query_mssql()。我的假设是,一旦我调用“完成”,如果成功则返回结果,如果错误则返回fulfill()。

上面的函数是 query_mcafee_mssql(),它忽略错误或成功,只是传递结果。

函数computeCurrentDefinitionResult() 是所有问题出现的地方。我需要一个接一个地进行两个 sql 查询。但是,如果第一个查询失败,那么我看不到继续下一个查询的任何意义

query_mcafee_mssql(leaf_sql_query)
        .then(function (LeafNode) {
             if (LeafNode == undefined) {
              fulfill(LeafNode);
             } else {
              return LeafNode;
             }
        })

我不希望 .then 的其余部分被执行,因为如果 LeafNode 未定义则没有意义。我想将 LeafNode 值返回给它的调用者。但是,如果我返回fulfill(),代码流似乎会移动到下一个.then。如果我使用reject(),调用者query_mcafee_mssql_type() .then 块不会被调用。相关块如下所示。

computeCurrentDefinitionResult(database, node_name)
              .then(function (result) {
                console.log('query_mcafee_mssql_type' + result);
                fulfill(result);
              });

- 如何从 computeCurrentDefinitionResult() 返回实际结果? - 是否所有功能都需要返回“Promise”才能实现我正在做的事情? - 为什么调用“fulfill()”后代码补丁没有从函数中返回? - 这些功能块中是否需要使用“return”? 任何帮助,将不胜感激。谢谢。

【问题讨论】:

  • 我建议您阅读“承诺反模式”herehere,因为您的代码中有一些内容。
  • 看看 Promise.defer() - 如果反模式应该解决大多数问题。 :)
  • 谢谢大家,我正在努力研究反模式”。我发现我的代码有很多问题,但逻辑本身是否存在根本性问题?
  • 我阅读了一些关于 Anti-pattern 的文章,但我仍然感到困惑。我意识到 q.all() 不是我需要使用 computeCurrentDefinitionResult() 因为我需要我的第一个异步调用的结果来决定是否需要调用下一个异步调用。有人能指出我的 computeCurrentDefinitionResult() 函数存在哪些反模式问题吗?

标签: javascript node.js promise


【解决方案1】:

从您的代码中,我感觉您不知道 Promise 中 resolvereject 的正确用法。这是正确的。

function query_mssql(config, sql_string){
  return new Promise(function (resolve, reject) {
    var connection = new sql.Connection(config, function(err) {
      // ... error checks 
      if (err) {
        return reject(err);
      }
      // Query 
      var request = new sql.Request(connection); 
      request.query(sql_string, function(err, recordset) {
        // ... error checks should go here :
        if (err) {
            return reject(er);
        }
        // output query result to console:
        //console.log(recordset);
        resolve(recordset);
      });
    });
  });
}
//Then use it like this
query_mssql(config,sql_string)
.then(function(LeafNode){
    //query success
    console.log(LeafNode);
}).catch(function(er){
    //query failed,
    console.log(er);
});

【讨论】:

  • 这是否意味着您的示例中函数 query_mssql(config,sql_string) 的调用者将是 computeCurrentDefinitionResult(database, node_name)。因此,如果我为该函数添加一个 .catch ,那么 er 将一直向上花费到我的大部分堆栈的顶部?这就是我试图理解的。感谢您的提示。
  • 是的。而且,您只需在 Promise 链中 catch 一次。
  • 您的意思是 catch 必须为堆栈中存在 .then 的每个函数添加 catch。这必须始终跟在 .catch 之后,对吗?
  • 我的意思是无论调用多少个then函数,你只需要在Promise链的末尾调用一次catch
猜你喜欢
  • 2018-09-09
  • 2018-02-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-15
  • 2017-01-06
  • 2015-11-14
  • 1970-01-01
  • 2021-02-04
相关资源
最近更新 更多