我遇到的问题是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();
});
});
});
除了最后一个断言之外,所有上述断言都会通过,这会在模型中引发错误,这个错误永远不会被拾取并传递给客户端。
答案 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');
}
希望有人觉得这很有用。