Angular 获取 - 地图中的地图
Angular get - map inside map
我正在尝试调用 map 中的 API 方法,但从未进行过第二个 API 调用。没有控制台错误。
//This method is not being called - Not hitting the API method
this.getUserPermissions(localStorage.getItem('user_ref'));
只是想知道我是否不能在 map 中调用 map?
下面是我的代码。
public isAuthenticated() {
if (!this.loggedIn)
this.redirectToLogin();
return this.httpClient.get<boolean>(`${this.settings.getApiSettings('uri')}/api/auth/IsTokenValid`, {
params: { token: this.getToken }
}).map( /// <<<=== use `map` here
(response) => {
if (response !== null) {
var receivedToken = response["securityStamp"];
var availableToken = localStorage.getItem('access_token');
//Check if received a refreshed token. (tokens are refreshed every 15 minutes)
if (receivedToken && receivedToken !== availableToken) {
localStorage.removeItem('access_token');
localStorage.setItem('access_token', response["securityStamp"]);
}
this.user_permissions = this.getUserPermissions(localStorage.getItem('user_ref'));
}
let data = response;
if (data == null)
return false;
else
return true;
}
);
}
getUserPermissions(user_ref) {
if (!this.loggedIn)
this.redirectToLogin();
const httpParams: HttpParamsOptions = { userRef: "44C4D2F7-76A0-4714-B8CA-3123F607AC5A" } as HttpParamsOptions;
const httpOptions = {
params: new HttpParams(httpParams),
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.getToken
})
};
return this.httpClient.get<Array<any>>(`${this.settings.getApiSettings('uri')}/api/auth/GetUserPermissions`, httpOptions).map( /// <<<=== use `map` here
(response) => {
if (response["status"] == 401) {
this.redirectToLogin();
}
else if (response["status"] < 200 || response["status"] >= 300) {
throw new Error('This request has failed ' + response["status"]);
}
this.user_permissions = response;
return response;
}
);
}
那是因为 .map()
函数不是 return 订阅而是可观察的。
如果您需要与来自 HttpClient 的 api 调用的响应进行交互,那么您需要订阅您正在调用的 .get()
或 .post()
方法。
这可能会满足您的需要,或者至少在控制台中记录它以防请求失败。
firstUrl = `${this.settings.getApiSettings('uri')}/api/auth/IsTokenValid`;
secondUrl = `${this.settings.getApiSettings('uri')}/api/auth/GetUserPermissions`;
public isAuthenticated() {
if (!this.loggedIn) this.redirectToLogin();
return this.httpClient.get<boolean>(this.firstUrl, {params: {token: this.getToken}}).subscribe(
(response) => {
if (response !== null) {
let receivedToken = response["securityStamp"];
let availableToken = localStorage.getItem('access_token');
if (receivedToken && receivedToken !== availableToken) {
localStorage.removeItem('access_token');
localStorage.setItem('access_token', response["securityStamp"]);
}
this.user_permissions = this.getUserPermissions(localStorage.getItem('user_ref'));
}
return response != null;
},
(error) => console.log(error)
);
}
getUserPermissions(user_ref) {
if (!this.loggedIn) this.redirectToLogin();
const httpParams: HttpParamsOptions = {userRef: "44C4D2F7-76A0-4714-B8CA-3123F607AC5A"} as HttpParamsOptions;
const httpOptions = {
params: new HttpParams(httpParams),
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.getToken
})
};
return this.httpClient.get<Array<any>>(this.secondUrl, httpOptions).subscribe(
(response) => {
if (response["status"] == 401) {
this.redirectToLogin();
} else if (response["status"] < 200 || response["status"] >= 300) {
throw new Error('This request has failed ' + response["status"]);
}
this.user_permissions = response;
return response;
},
(error) => console.log(error)
);
}
您使用的是什么版本的 Angular(更重要的是 rxjs)?
记住 HttpClient returns 和 Observable(一个懒惰的 observable,在您订阅它之前不会做任何事情)。
作为您的 isAuthenticated
方法 returns 一个 HttpClient Get 方法,您的 isAuthenticated
returns 一个等待订阅的可观察对象。
订阅 HttpClient observable 将进行 http 调用,在收到响应时调用观察者下一个处理程序,如果提供,也会调用 on complete 处理程序。我建议在这里阅读 Observables。
https://www.learnrxjs.io/
// Doing this will not do anything as the observable has not been subscribed to.
this.httpClient.get<boolean>(`...`);
// Subscribing to the HttpClient will make the request
this.httpClient.get<boolean>(`...`)
.subscribe((response) => {
// do something with the response
});
正如您所说的第一个 HttpCall 已创建,我假设您在调用它时订阅了 isAuthenticated
方法?即
isAuthenticated().subscribe( (response) => {
//
})
请注意,您的 getUserPermissions
也 returns 一个 HttpClient 方法(一个可观察的),但是当您调用它时 this.getUserPermissions(localStorage.getItem('user_ref'));
它从未被订阅,因此从未被调用。
要发起第二个请求,您必须订阅 getUserPermissions
调用,如下所示。
public isAuthenticated() {
// ...
return this.httpClient.get<boolean>('...').map(
(response) => {
// Subscribe to the second Http call
this.getUserPermissions(localStorage.getItem('user_ref'))
.subscribe( (response) => {
// do something with the second
})
})
}
一些旁注;
从 rxjs v6 开始,您链接到 httpClient.get
方法的 map
运算符已被弃用,取而代之的是管道运算符。
参见:https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/migration.md
所以这个
this.httpClient.get<boolean>('...')
.map( ... )
.subscribe(...)
现在应该这样写:
this.httpClient.get<boolean>('...')
.pipe( // <- Pipe the operators
map( ... ),
map( ... )
)
.subscribe( ...)
尽管在原始问题之外,我会考虑重构您的代码并使用可用的 rxjs/operators 来实现更好的流程控制。
this.httpClient.get<boolean>('...')
.pipe(
map(( response ) => {
// some logic
return something;
}),
map( (something) => localStorage.getItem('user_ref')),
switchMap( (userRef) => this.getUserPermissions(userRef)), // <- switchMap to a new observable
)
.subscribe( (responseFromGetUserPermissions) => {
// This value is now the return of getUserPermissions because of switchMap
})
rxjs / observable 是一个非常强大的模式,我强烈建议花大量时间学习如何充分利用它们。
问候
乔诺
当然你可以在地图中调用地图,但是这里你没有调用 API 的问题是因为你的方法 "getUserPermissions" 返回的是 Observable 而不是用户的数据。
我建议您按照反应式方法更改这部分的设计。
你可以阅读这个link。
希望对你有帮助
我正在尝试调用 map 中的 API 方法,但从未进行过第二个 API 调用。没有控制台错误。
//This method is not being called - Not hitting the API method
this.getUserPermissions(localStorage.getItem('user_ref'));
只是想知道我是否不能在 map 中调用 map?
下面是我的代码。
public isAuthenticated() {
if (!this.loggedIn)
this.redirectToLogin();
return this.httpClient.get<boolean>(`${this.settings.getApiSettings('uri')}/api/auth/IsTokenValid`, {
params: { token: this.getToken }
}).map( /// <<<=== use `map` here
(response) => {
if (response !== null) {
var receivedToken = response["securityStamp"];
var availableToken = localStorage.getItem('access_token');
//Check if received a refreshed token. (tokens are refreshed every 15 minutes)
if (receivedToken && receivedToken !== availableToken) {
localStorage.removeItem('access_token');
localStorage.setItem('access_token', response["securityStamp"]);
}
this.user_permissions = this.getUserPermissions(localStorage.getItem('user_ref'));
}
let data = response;
if (data == null)
return false;
else
return true;
}
);
}
getUserPermissions(user_ref) {
if (!this.loggedIn)
this.redirectToLogin();
const httpParams: HttpParamsOptions = { userRef: "44C4D2F7-76A0-4714-B8CA-3123F607AC5A" } as HttpParamsOptions;
const httpOptions = {
params: new HttpParams(httpParams),
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.getToken
})
};
return this.httpClient.get<Array<any>>(`${this.settings.getApiSettings('uri')}/api/auth/GetUserPermissions`, httpOptions).map( /// <<<=== use `map` here
(response) => {
if (response["status"] == 401) {
this.redirectToLogin();
}
else if (response["status"] < 200 || response["status"] >= 300) {
throw new Error('This request has failed ' + response["status"]);
}
this.user_permissions = response;
return response;
}
);
}
那是因为 .map()
函数不是 return 订阅而是可观察的。
如果您需要与来自 HttpClient 的 api 调用的响应进行交互,那么您需要订阅您正在调用的 .get()
或 .post()
方法。
这可能会满足您的需要,或者至少在控制台中记录它以防请求失败。
firstUrl = `${this.settings.getApiSettings('uri')}/api/auth/IsTokenValid`;
secondUrl = `${this.settings.getApiSettings('uri')}/api/auth/GetUserPermissions`;
public isAuthenticated() {
if (!this.loggedIn) this.redirectToLogin();
return this.httpClient.get<boolean>(this.firstUrl, {params: {token: this.getToken}}).subscribe(
(response) => {
if (response !== null) {
let receivedToken = response["securityStamp"];
let availableToken = localStorage.getItem('access_token');
if (receivedToken && receivedToken !== availableToken) {
localStorage.removeItem('access_token');
localStorage.setItem('access_token', response["securityStamp"]);
}
this.user_permissions = this.getUserPermissions(localStorage.getItem('user_ref'));
}
return response != null;
},
(error) => console.log(error)
);
}
getUserPermissions(user_ref) {
if (!this.loggedIn) this.redirectToLogin();
const httpParams: HttpParamsOptions = {userRef: "44C4D2F7-76A0-4714-B8CA-3123F607AC5A"} as HttpParamsOptions;
const httpOptions = {
params: new HttpParams(httpParams),
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.getToken
})
};
return this.httpClient.get<Array<any>>(this.secondUrl, httpOptions).subscribe(
(response) => {
if (response["status"] == 401) {
this.redirectToLogin();
} else if (response["status"] < 200 || response["status"] >= 300) {
throw new Error('This request has failed ' + response["status"]);
}
this.user_permissions = response;
return response;
},
(error) => console.log(error)
);
}
您使用的是什么版本的 Angular(更重要的是 rxjs)?
记住 HttpClient returns 和 Observable(一个懒惰的 observable,在您订阅它之前不会做任何事情)。
作为您的 isAuthenticated
方法 returns 一个 HttpClient Get 方法,您的 isAuthenticated
returns 一个等待订阅的可观察对象。
订阅 HttpClient observable 将进行 http 调用,在收到响应时调用观察者下一个处理程序,如果提供,也会调用 on complete 处理程序。我建议在这里阅读 Observables。 https://www.learnrxjs.io/
// Doing this will not do anything as the observable has not been subscribed to.
this.httpClient.get<boolean>(`...`);
// Subscribing to the HttpClient will make the request
this.httpClient.get<boolean>(`...`)
.subscribe((response) => {
// do something with the response
});
正如您所说的第一个 HttpCall 已创建,我假设您在调用它时订阅了 isAuthenticated
方法?即
isAuthenticated().subscribe( (response) => {
//
})
请注意,您的 getUserPermissions
也 returns 一个 HttpClient 方法(一个可观察的),但是当您调用它时 this.getUserPermissions(localStorage.getItem('user_ref'));
它从未被订阅,因此从未被调用。
要发起第二个请求,您必须订阅 getUserPermissions
调用,如下所示。
public isAuthenticated() {
// ...
return this.httpClient.get<boolean>('...').map(
(response) => {
// Subscribe to the second Http call
this.getUserPermissions(localStorage.getItem('user_ref'))
.subscribe( (response) => {
// do something with the second
})
})
}
一些旁注;
从 rxjs v6 开始,您链接到 httpClient.get
方法的 map
运算符已被弃用,取而代之的是管道运算符。
参见:https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/migration.md
所以这个
this.httpClient.get<boolean>('...')
.map( ... )
.subscribe(...)
现在应该这样写:
this.httpClient.get<boolean>('...')
.pipe( // <- Pipe the operators
map( ... ),
map( ... )
)
.subscribe( ...)
尽管在原始问题之外,我会考虑重构您的代码并使用可用的 rxjs/operators 来实现更好的流程控制。
this.httpClient.get<boolean>('...')
.pipe(
map(( response ) => {
// some logic
return something;
}),
map( (something) => localStorage.getItem('user_ref')),
switchMap( (userRef) => this.getUserPermissions(userRef)), // <- switchMap to a new observable
)
.subscribe( (responseFromGetUserPermissions) => {
// This value is now the return of getUserPermissions because of switchMap
})
rxjs / observable 是一个非常强大的模式,我强烈建议花大量时间学习如何充分利用它们。
问候 乔诺
当然你可以在地图中调用地图,但是这里你没有调用 API 的问题是因为你的方法 "getUserPermissions" 返回的是 Observable 而不是用户的数据。
我建议您按照反应式方法更改这部分的设计。
你可以阅读这个link。
希望对你有帮助