我的用例是:
>用户从我们的API请求资产因JWT过期而失败(作为httpOnly cookie传递) – API返回401状态代码.
>我们再次使用refresh_token来验证它们(无需用户做任何事情),以便从我们的客户端请求auth0来检索新的JWT.
>我们将新的JWT发送到我们的API,将其设置为httpOnly cookie以替换过期的cookie.
>然后,我们想要重试用户在步骤1中对API所做的原始请求.
我正在尝试使用redux-observable在我的Redux应用程序中使用Observable.如果你能想到使上述用户流程工作的另一种方式,我会很高兴听到如何.
NB.我使用rxjs V5
export const fetchAssetListEpic = (action$, store) => {
return action$.ofType('FETCH_ASSET_LIST')
.switchMap( action => {
const options = {
crossDomain: true,
withCredentials: true,
url: uriGenerator('assetList', action.payload)
};
return ajax(options);
})
.map(fetchAssetListSuccess)
.retryWhen(handleError)
.catch(redirectToSignIn);
};
function handleError(err) {
return (err.status === 401) ?
/* Authenticate here [Step 2] */
/* Send new JWT to API [Step 3] */
/* If successful make original request again [Step 4] */
:
Observable.throw(err);
}
function redirectToSignIn() {
/*I will redirect here*/
}
到目前为止,我能够完成第1步,第2步和第3步,但不太确定添加第4步的方法.我可能完全不合适但任何帮助都会很棒!
解决方法:
好吧,你可能不想做的一件事是允许错误进入*流.即使你做了捕获,你也有效地杀死了*流.因此,除非您的重定向通过像react-router之类的东西进行硬重定向而不是软重定向,否则您将无法再使用此史诗.
因此,我想说您希望将大部分逻辑封装在switchMap中:
function withAuthorizedFlow(source) {
return source
.map(fetchAssetListSuccess)
// retryWhen takes a callback which accepts an Observable of errors
// emitting a next causes a retry, while an error or complete will
// stop retrying
.retryWhen(e => e.flatMap(err =>
Observable.if(
// Returns the first stream if true, second if false
() => err.status === 401,
reauthenticate, // A stream that will emit once authenticated
Observable.throw(err) // Rethrow the error
))
)
.catch(redirectToSignIn);
}
/** Within the epic **/
.switchMap(({payload}) => {
const options = {
crossDomain: true,
withCredentials: true,
url: uriGenerator('assetList', payload)
};
// Invoke the ajax request
return ajax(options)
// Attach a custom pipeline here
// Not strictly necessary but it keeps this method clean looking.
.let(withAuthorizedFlow);
})
使用上面的let是完全可选的,我把它扔进去清理函数.基本上,虽然您希望将错误包含在内部流中,以便它不能停止外部流.我不确定你使用的是哪个ajax库,但是你也应该确认它实际上会返回一个冷的Observable,否则你需要将它包装在一个延迟块中以便重试时才能工作.