【问题标题】:Understanding promise rejection in node.js了解 node.js 中的承诺拒绝
【发布时间】:2017-02-05 23:03:32
【问题描述】:

我正在尝试理解 node.js 中的承诺。这是一个示例代码

con.queryReturnPromise("SELECT * FROM bookings WHERE driverId = " + accId + " AND bookingStatus = " + config.get('BOOKING_STATUS_ACTIVE') + " LIMIT 1")
  .catch((err) => {

    callback({
      "message": "Success",
      "error": true,
    });
    console.log("mysql query error");
    return Promise.reject();
  })
  .spread((rows, fields) => {
    if (rows.length != 1) {
      return Promise.reject();
    }
    mBooking = rows[0];
    var query = "INSERT INTO locations SET timeStamp = " + timeStamp + " latitude = " + lat + ", longitude = " + lng + ", bookingId = " + mBooking.id;
    return con.queryReturnPromise(query)
  })
  .catch((err) => {
    if (err)
      console.log("Adding Location error" + err);
    return Promise.reject();
  })
  .spread(() => {
    return funcs.getBooking(con, mBooking.id)
  })
  .then((booking) => {
    if (mBooking.userId.toString() in userSockets) {
      userSockets[mBooking.userId].emit(config.get('EVENT_USER_UPDATE_BOOKING'), {
        "message": "Success",
        "error": false,
        "booking": booking
      });
      userId = mBooking.userId.toString();
    }
    callback({
      "message": "Success",
      "error": false,
      "booking": booking
    });
  })
  .catch((err) => {
    if (err)
      console.log(err);
  });

代码很简单。但是我有一个困惑。如果正在调用return Promise.reject(),该函数将指向何处,将调用哪个代码。例如,如果第一个 catch 子句被调用并且它调用 return Promise.reject() 下面的部分代码将在之后运行

for 循环中的承诺

data = JSON.parse(data);
            var promisesArray = [];
            for (var i = 0; i < data.length; i++) 
            {
                var location = data[i];
                var lng       = location.lng;
                var lat       = location.lat;
                var bearing   = location.bearing;
                var deltaTime = location.deltaTime;
                var timeStamp = location.timeStamp;

                var query = "INSERT INTO locations SET timeStamp = " + timeStamp + " latitude = " + lat + ", longitude = " + lng + ", bookingId = " + mBooking.id;


                var promise = con.queryReturnPromise(query)                    
                        .then( () => {                            
                        });

                promisesArray[] = promise;
            }

            Promise.all(promisesArray)
            .then(function(results)
            {
                    callback({
                        "error": false,
                    });            
            });

【问题讨论】:

  • 如果我错了,请纠正我,但链中应该只有一个 catch() 方法调用。如果你想支持在每一步之后捕获错误,那么你应该在 then() 方法中提供错误回调作为第二个参数。
  • 请注意:当您使用 ES2015 语法时,不鼓励使用 .spread(),请改用 .then(([rows, fields]) =&gt; { ... })
  • @MadaraUchiha 为什么不鼓励?性能?
  • @thefourtheye 可能,但我认为这与便携性有关。 .spread() 仅在 Bluebird 中可用,而 .then(([]) =&gt; 在所有 Promise 实现中可用。

标签: javascript node.js promise


【解决方案1】:

每次执行return Promise.reject() 时,都会调用该链中的下一个.catch() 处理程序。它将跳过任何.then() 处理程序,直到下一个.catch() 处理程序。

.then() 处理程序或.catch() 处理程序返回拒绝承诺会使当前承诺链被拒绝。因此,随着链中遇到更多处理程序,链中的下一个拒绝处理程序将被调用。

当您点击.catch() 处理程序时,.catch() 之后会发生什么取决于.catch() 所做的事情。如果它抛出或返回一个被拒绝的 Promise,则该 Promise 将保持被拒绝状态,并且链中的下一个 .catch() 将执行。如果它不返回任何内容或任何常规值(最终拒绝的承诺除外),则承诺将被解决(不再拒绝),然后链中的下一个 .then() 处理程序运行。

这是一个例子:

a().then(function() {
    // makes promise chain assume rejected state
    return Promise.reject();
}).then(function() {
    // this will not get called because promise is in rejected state
}).catch(function() {
    // this will get called
    // returning a reject promise will keep the promise in the reject state
    return Promise.reject();
}).then(function() {
    // this will not get called because promise is in rejected state
}).catch(function() {
    // this will get called
    return 2;
}).then(function(val) {
    // this will get called because prior `.catch()` "handled" the rejection
    // already
    console.log(val);    // logs 2
}).catch(function() {
     // this is not called because promise is in resolved state
});

【讨论】:

  • 所以如果我在第一个 catch 子句中被拒绝,那么我的代码中的所有 catch 子句都会系统地运行?
  • @MuhammadUmar - 不。只有该链中的下一个.catch() 运行。 .catch() 之后发生的事情取决于 .catch() 返回或抛出的内容。如果它返回一个被拒绝的承诺或抛出一个异常,那么下一个.catch() 将运行。如果它不返回任何内容或返回正常值,则 promise 将被解析并且下一个 .then() 处理程序将运行。
  • 如果你看到我的代码,下一个 catch 有错误,然后再次返回拒绝。所以控制台会记录一个错误并切换到下一个catch
  • @MuhammadUmar - 看看我在之前的评论中添加了什么。
  • 谢谢,这很有帮助,一个问题,如果我必须在 for 循环中更新查询,你能解释一下它的语法,例如,如果我必须更新 10 行
猜你喜欢
  • 1970-01-01
  • 2017-06-04
  • 2018-01-18
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 2019-08-06
  • 2013-06-22
  • 1970-01-01
相关资源
最近更新 更多