Promise拒绝

时间:2016-09-28 06:04:38

标签: mysql node.js callback promise

我正在做一个包含在promise中的简单数据库调用,并试图捕获错误并将其传递给promise reject(),但拒绝不会被调用代码处理或冒泡回来。当mysql调用失败时,代码就会停止执行。

mysql回调中的错误是:

  

REJECTING QUERY {错误:您的SQL语法出错;检查与您的MariaDB服务器版本对应的手册,以便在'?'附近使用正确的语法在第1行

这是数据库查询代码:

this.query = function(sql, params) {
    return new Promise((resolve, reject) => {
        _pool.query(sql, params, function(err, result) {
            if (err) {
                console.log("REJECTING QUERY", err);
                return reject(err);
            }
            resolve(result);
        });
    });
}

这是调用代码:

this.createUser = function(data) {
    var query = "INSERT into users SET ?";

    return new Promise((resolve, reject) => {
        Container.DB.query(query, data)
            .then((response) => {
                console.log("Resolved", response);
                return resolve(response);
            },(error) => {
                console.log("REJECTION ERROR", error);
                return reject('An unknown error occurred and has been reported.');
            })
            .catch((err) => {
                console.log("CAUGHT ERROR", err);
            });
    });
}

我在数据库查询代码中得到“REJECTING QUERY”,但是没有到达调用代码(即.then,或错误处理程序或.catch处理程序)。 是否有可能让mysql错误在代码中达到这些点,以便我可以响应用户?我做错了吗?

1 个答案:

答案 0 :(得分:1)

@JaromandaX提到的反模式迫使你不必要地跳过燃烧的箍以适应它......并且你被烧伤了。

但是,首先,你在then之前拒绝来自catch的外部(冗余)承诺,因此catch被绕过。在一个promise链中抛出一个错误后,带有第二个参数的第一个 thenable onRejected )将消耗它:所以它不会被传播到那个之外。但是,无论如何,你需要将错误记录在你拒绝的外部承诺上。

this.createUser = function (data) {
  var query = "INSERT into users SET ?";

  return new Promise((resolve, reject) => {  //   the first 'then' rejects to here
    Container.DB.query(query, data)          //   broken promise: anti-pattern
      .then((response) => {
        console.log("Resolved", response);
        return resolve(response);
      }, (error) => {
        console.log("REJECTION ERROR", error);//<--the error is consumed here and will
                                              //   not go any further on this chain
        return reject('An unknown error occurred and has been reported.');
      })
      .catch((err) => {                       //   this will not be called
        console.log("CAUGHT ERROR", err);     //   because it is the 'onRejected'
                                              //   argument of a then
      });
  })
    .catch((err) => {   // this will be called and the error will be consumed
      console.log("CAUGHT ERROR", err);
      return 'An unknown error occurred and has been reported.';
    });
  ;
}

更糟糕的是,您可以在一个catch ...

中记录并重新抛出错误
this.createUser = function (data) {
  var query = "INSERT into users SET ?";

  return new Promise((resolve, reject) => {  // this is still redundant
    Container.DB.query(query, data)          // broken promise: anti-pattern
      .then((response) => {                  // on error, skip this because it has no
        console.log("Resolved", response);   // 'onRejected' argument
        return resolve(response);
      })
      .catch((err) => {                      // this will be called and the error
        console.log("CAUGHT ERROR", err);    // will be consumed
        return reject('An unknown error occurred and has been reported.');
      });
  })
    ;
}

更好的是,消除反模式,并在(冗余)承诺包装器上使用throw而不是reject传播消息...

this.createUser = function (data) {
  var query = "INSERT into users SET ?";

  return Container.DB.query(query, data)
    .then((response) => {                  // on error, skip this because it has no
      console.log("Resolved", response);   // 'onRejected' argument
      return resolve(response);
    })
    .catch((err) => {                      // this will be called and the error
      console.log("CAUGHT ERROR", err);    // will be consumed so need to re-throw
      throw new Error('An unknown error occurred and has been reported.');
    });
}

请注意,catch只是then(undefined, reject)的语法糖,一旦被拒绝,承诺就不再是待定,称之为then { {1}}方法会尽快返回undefined&#39;。所以如果你不想抛出那么你可以在捕获之后链接另一个...

this.createUser = function (data) {
  var query = "INSERT into users SET ?";

  return Container.DB.query(query, data)
    .then((response) => {                  // on error, skip this because it has no
      console.log("Resolved", response);   // 'onRejected' argument
      return resolve(response);
    })
    .catch((err) => {                      // this will be called and the error
      console.log("CAUGHT ERROR", err);    // will be consumed. The returned promise
    })                                     // state will be rejected but not pending
                                           // It's then method returns 'undefined' as 
                                           // soon as possible
    .then(() => 'An unknown error occurred and has been reported.');
}

更进一步,请记住,已解决或拒绝的承诺返回的值是调用的那些值的返回值,您可以通过return将您喜欢的任何值传递给消费者在catch ...

this.createUser = function (data) {
  var query = "INSERT into users SET ?";

  return Container.DB.query(query, data)
    .then((response) => {                  // on error, skip this because it has no
      console.log("Resolved", response);   // 'onRejected' argument
      return resolve(response);
    })
    .catch((err) => {                      // this will be called and the error
      console.log("CAUGHT ERROR", err);    // will be consumed. The returned promise
                                           // state will be rejected but not pending
                                           // but you can still return any value
      return 'An unknown error occurred and has been reported.'
    })
}