RxJs没有捕获抛出的错误

时间:2016-10-27 11:50:56

标签: javascript rxjs

我遇到的问题是RxJ没有捕获来自可观察流的异常。

以下是我的代码。

const Rx = require('rx');
if (process.env.NODE_ENV === 'development') {
  require('dotenv').load();
}

const getTransactionsVerificationStatus = (params, models, retryLimit = process.env.CARD_VERIFICATION_ATTEMPTS_LIMIT) => {
  const potCheckResult$ = models.pot().exists([params.userId, params.potId]);

  const needsVerified$ = models.transaction()
    .listUnverifiedCards([params.userId, params.potId])
    .map(card => {
      return {
        status: 'success',
        data: {
          card: {
            id: card.id,
            cardNumberMask: card.cardNumberMask,
            attemptsRemaining: (retryLimit - card.attempts),
            chargeDate: card.chargeDate,
            expiry: card.expiry,
            status: card.status
          },
          requiresVerification: true
        }
      };
    })
    .take(1);

  const verified$ = models.user()
    .getDefaultCard([params.userId])
    .map(card => {
      return {
        status: 'success',
        data: {
          card: {
            id: card.id,
            cardNumberMask: card.cardNumberMask,
            attemptsRemaining: (retryLimit - card.attempts),
            chargeDate: card.chargeDate,
            expiry: card.expiry,
            status: card.status
          },
          requiresVerification: false
        }
      };
    })
    .take(1);

  const error$ = potCheckResult$
    .filter(x => x.len <= 0)
    .map(() => {
      return {
        status: 'error',
        message: ['Requested pot does not exist for current user']
      };
    });

  return Rx.Observable
    .concat(error$, needsVerified$, verified$)
    .take(1)
    .catch(e => {
      logger.warn(e);

      return Rx.Observable.just(
        {
          status: 'error',
          type: 'array',
          data: ['Something went wrong']
        }
      );
    });
};

module.exports = getTransactionsVerificationStatus;

基本上,这里有三个可观察的流,它们与concat方法合并。

问题是如果这些模型中的任何一个抛出异常,它就不会被catch方法捕获。我如何捕获这些例外?

非常感谢任何帮助!

编辑:

为了完整性,以下是我在上面的代码上运行的测试。

const chai = require('chai');
chai.use(require('chai-json-schema'));
const expect = chai.expect;
const getTransactionsVerificationStatus = require('../get-transactions-verification-status');
const Rx = require('rx');

describe('Get Transactions Verification Logic', function() {
  let models;

  beforeEach(function() {
    // Mock models
    models = (params) => {
      return {
        pot: () => {
          return {
            exists: () => {
              if(params.potExists) {
                return Rx.Observable.just({
                  len: params.potExists
                }).toArray()
              } else {
                return Rx.Observable.just({
                  len: 0
                });
              }
            }
          }
        },
        transaction: () => {
          return {
            listUnverifiedCards: () => {
              if(params.error) {
                throw new Error('This is an error!');
              }
              if (params.unverifiedCards) {
                return Rx.Observable.just({
                  id: "unverified card",
                  cardNumberMask: 123456,
                  attempts: 0,
                  chargeDate: null,
                  expiry: 2016123,
                  status: 'UNVERIFIED'
                });
              } else {
                return Rx.Observable.empty()
              }
            }
          };
        },
        user: () => {
          return {
            getDefaultCard: () => Rx.Observable.just(
              {
                id: "verified card",
                cardNumberMask: 123456,
                attempts: 0,
                chargeDate: null,
                expiry: 2016123,
                status: 'VERIFIED'
              }
            )
          };
        }
      };
    };
  });

  it('should return a non-verified card if one has been used in a transaction', done => {
    const params = {
      userId: 123,
      potId: 123
    };

    const modelParams = {
      potExists: 1,
      unverifiedCards: true
    };

    const response$ = getTransactionsVerificationStatus(
      params,
      models(modelParams),
      3
    );

    response$.subscribe(json => {
      expect(json).to.deep.equal({
        status: "success",
        data: {
          card: {
            id: "unverified card",
            cardNumberMask: 123456,
            attemptsRemaining: 3,
            chargeDate: null,
            expiry: 2016123,
            status: 'UNVERIFIED'
          },
          "requiresVerification": true
        }
      });
      done();
    });
  });

  it('should return the active card if no transactions have used an unverified card', done => {
    const params = {
      userId: 123,
      potId: 123
    };

    const modelParams = {
      potExists: 1,
      unverifiedCards: false
    };

    const response$ = getTransactionsVerificationStatus(
      params,
      models(modelParams),
      3
    );

    response$.subscribe(json => {
      expect(json).to.deep.equal({
        status: "success",
        data: {
          card: {
            id: "verified card",
            cardNumberMask: 123456,
            attemptsRemaining: 3,
            chargeDate: null,
            expiry: 2016123,
            status: 'VERIFIED'
          },
          "requiresVerification": false
        }
      });
      done();
    });
  });

  it('should return an error message if the user does not have a pot with the id requested', done => {
    const params = {
      userId: 1,
    };

    const modelParams = {
      potExists: 0,
      unverifiedCards: false,
      verifiedCards: false
    };

    const response$ = getTransactionsVerificationStatus(
      params,
      models(modelParams),
      3
    );

    response$.subscribe(json => {
      expect(json).to.deep.equal({
        status: 'error',
        message: ['Requested pot does not exist for current user']
      });
      done();
    });
  });

  it('should handle all other errors', done => {
    const params = {
      userId: 1,
    };

    const modelParams = {
      potExists: 1,
      unverifiedCards: true,
      error: true
    };

    const response$ = getTransactionsVerificationStatus(
      params,
      models(modelParams),
      3
    );

    response$.subscribe(json => {
      expect(json).to.deep.equal({
        status: 'error',
        type: 'array',
        data: ['Something went wrong']
      });
      done();
    });
  });
});

除了最后一个断言之外,所有上述断言都会通过,这会在模型中引发错误,这个错误永远不会被拾取并传递给客户端。

2 个答案:

答案 0 :(得分:0)

在连接的流中,在concat之后你有take(1)运算符。这意味着您将只收听第一个值。然后,take运算符将执行隐式取消订阅。这意味着,如果第一个值不是错误,则不会有下一个事件,因此您的“捕获”不会出现错误。接线员。

其次,您未在示例中订阅此流。这只是在您的代码上面或现实生活中。如果您没有订阅您的信息流,则不会启动信息流(因为您通常使用冷观察系统来查看我所看到的信息)。

答案 1 :(得分:0)

我明白了。

问题在于测试,而不是getTransactionsVerificationStatus功能。

问题是我抛出的错误应该是从一个可观察的抛出。这是我更新的代码。

  if (params.error) {
    return Rx.Observable.create(() => {
      throw new Error('Data error');
    });
  }

这不是

  if (params.error) {
    throw new Error('Data error');
  }

希望有人觉得这很有用。