将 promises 与 HttpInterceptor observables 混合使用?
issue mixing promises with HttpInterceptor observables?
我正在使用 HttpInterceptor 重新发送带有令牌的请求,以防它们 return 出现 401。
这在我刚刚获取缓存的令牌之前一直很有效。由于 Firebase 令牌似乎不会自动刷新(尽管使用 forceRefresh),我现在试图在拦截器中实时获取新令牌 class。问题是现在请求没有被重新发送。
这是我的完整拦截器:
export class CustomHttpInterceptor implements HttpInterceptor {
constructor(private injector: Injector) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const formRequest = req.clone({ headers: req.headers.set('Content-Type', 'application/x-www-form-urlencoded') });
return next.handle(formRequest).map((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
console.log("GOT RESPONSE WITHOUT ERROR. JUST PASSING THROUGH.");
return event;
}
}).catch(err => {
console.log("==INTERCEPTOR== CATCH ERROR RESPONSE");
if (err instanceof HttpErrorResponse) {
console.log("==INTERCEPTOR== IS HTTP ERROR RESPONSE");
if (err.status === 401) {
console.log("==INTERCEPTOR== IS 401");
let postParams = new HttpParams({ fromString: req.body });
if (postParams.has('t')) {
//401 while we already provided a token, so a real login is required
console.log("==INTERCEPTOR== PROVIDED TOKEN, STILL PROBLEM");
throw new Error("NOT_AUTH");
} else {
// most likely session expired, resend token
console.log("==INTERCEPTOR== REQUEST WAS WITHOUT TOKEN, RESEND WITH TOKEN");
// get AuthProvider here
const auth = this.injector.get(AuthProvider);
// token will come in a promise
return auth.getToken().then(idToken => {
console.log("GOT NEW TOKEN, resending request with token " + idToken);
//add token to post params
let newPostParams = postParams.append('t', idToken); ====> SUCCESFULLY GOT NEW TOKEN
//clone request and add new body
const changedReq = formRequest.clone({
method: 'POST',
body: newPostParams.toString()
});
return next.handle(changedReq); ====> THIS IS NOT PERFORMED
},
error => {
throw(error);
});
}
}
} else {
throw(err);
}
})
}
}
没有这个获取新令牌的承诺函数,正在使用最后一个 "next.handle(changedReq);" 重新发送请求。我没有发现我在这里做错了什么。这是因为我将 promises 与 observables 混在一起造成的吗?
通过按照 Rahul Singh 的建议将 promise 转换为 observable 并使用 flatMap 来实现嵌套的 observable return:
let promise = auth.getToken();
let observable = Observable.fromPromise(promise);
return observable.first().flatMap(idToken => {
console.log("GOT NEW TOKEN, resending request with token " + idToken);
//add token to post params
let newPostParams = postParams.append('t', idToken);
//clone request and add new body
const changedReq = formRequest.clone({
method: 'POST',
body: newPostParams.toString()
});
return next.handle(changedReq);
});
我正在使用 HttpInterceptor 重新发送带有令牌的请求,以防它们 return 出现 401。 这在我刚刚获取缓存的令牌之前一直很有效。由于 Firebase 令牌似乎不会自动刷新(尽管使用 forceRefresh),我现在试图在拦截器中实时获取新令牌 class。问题是现在请求没有被重新发送。
这是我的完整拦截器:
export class CustomHttpInterceptor implements HttpInterceptor {
constructor(private injector: Injector) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const formRequest = req.clone({ headers: req.headers.set('Content-Type', 'application/x-www-form-urlencoded') });
return next.handle(formRequest).map((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
console.log("GOT RESPONSE WITHOUT ERROR. JUST PASSING THROUGH.");
return event;
}
}).catch(err => {
console.log("==INTERCEPTOR== CATCH ERROR RESPONSE");
if (err instanceof HttpErrorResponse) {
console.log("==INTERCEPTOR== IS HTTP ERROR RESPONSE");
if (err.status === 401) {
console.log("==INTERCEPTOR== IS 401");
let postParams = new HttpParams({ fromString: req.body });
if (postParams.has('t')) {
//401 while we already provided a token, so a real login is required
console.log("==INTERCEPTOR== PROVIDED TOKEN, STILL PROBLEM");
throw new Error("NOT_AUTH");
} else {
// most likely session expired, resend token
console.log("==INTERCEPTOR== REQUEST WAS WITHOUT TOKEN, RESEND WITH TOKEN");
// get AuthProvider here
const auth = this.injector.get(AuthProvider);
// token will come in a promise
return auth.getToken().then(idToken => {
console.log("GOT NEW TOKEN, resending request with token " + idToken);
//add token to post params
let newPostParams = postParams.append('t', idToken); ====> SUCCESFULLY GOT NEW TOKEN
//clone request and add new body
const changedReq = formRequest.clone({
method: 'POST',
body: newPostParams.toString()
});
return next.handle(changedReq); ====> THIS IS NOT PERFORMED
},
error => {
throw(error);
});
}
}
} else {
throw(err);
}
})
}
}
没有这个获取新令牌的承诺函数,正在使用最后一个 "next.handle(changedReq);" 重新发送请求。我没有发现我在这里做错了什么。这是因为我将 promises 与 observables 混在一起造成的吗?
通过按照 Rahul Singh 的建议将 promise 转换为 observable 并使用 flatMap 来实现嵌套的 observable return:
let promise = auth.getToken();
let observable = Observable.fromPromise(promise);
return observable.first().flatMap(idToken => {
console.log("GOT NEW TOKEN, resending request with token " + idToken);
//add token to post params
let newPostParams = postParams.append('t', idToken);
//clone request and add new body
const changedReq = formRequest.clone({
method: 'POST',
body: newPostParams.toString()
});
return next.handle(changedReq);
});