我遇到了RxJs沒有捕獲可觀察流中的異常的問題。RxJs沒有捕獲拋出的錯誤
這是我的代碼的樣子。
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();
});
});
});
以上所有的斷言通過除了最後一個,它拋出一個錯誤的模型,這個錯誤是從來沒有拿起它使客戶端。
在這種情況下,我只想要一個值。我要麼需要一張有效的卡片列表,不要列出一個或者一個錯誤。錯誤是這個實例中最重要的項目,這就是爲什麼錯誤是'concat'方法中的第一項。 問題是,錯誤正在讓它瀏覽器。 該功能正在導出並訂閱到其他文件中。 我目前正在使用摩卡/柴測試人爲地拋出一個錯誤。如果我包含測試會有用嗎? –
你在哪裏拋出一個錯誤。在錯誤$的映射函數中,你正在返回一個對象而不是拋出錯誤。這可能是問題嗎? – KwintenP
聽起來可能是這個問題。我將如何捕捉它在地圖功能? 我認爲錯誤應該冒泡,直到它雖然抓住了。 –