Angular 可观察到 return 未定义的结果
Angular observable return undefined results
我有一个服务,我将用户令牌传递给服务器并将 return 结果传递给组件,但是当我的令牌存在时它保持 returning token: undefined
。
代码
Note: I commented each part for better understanding.
Service
export class GroupsService {
token: any;
constructor(
private storageIonic: NativeStorage,
private env: EnvService,
private http: HttpClient,
) {
// Get token
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
getGroups(): Observable<any> {
// I also add this here to make sure that i will get token in any case, yet it's returning undefined
if (this.token === undefined) {
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
console.log('token: ', this.token); // undefined
const httpOptions = {
headers: new HttpHeaders({
Authorization : this.token, //sending token to server
Accept: 'application/json, text/plain',
'Content-Type': 'application/json'
})
};
return this.http.get(`${this.env.GROUPS}`, httpOptions).pipe(
map(groups => groups)
);
}
}
Component
export class Tab1Page implements OnInit {
groups: any[] = [];
groupsOpts = {
loop: false,
slidesPerView: 3,
slidesPerColumn: 2
};
constructor(
private groupsService: GroupsService,
private menu: MenuController,
) {
this.menu.enable(true);
this.getGroups();
}
ngOnInit() {
//
}
// I added async/await yet result hasn't change.
async getGroups() {
await this.groupsService.getGroups().subscribe((res) => {
console.log('res: ', res);
console.log('res data: ', res.data);
console.log('res data data: ', res.data.data);
for (const group of res.data) {
this.groups.push(group);
}
});
}
}
知道如何解决这个问题吗?
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
这个调用是异步的,你不会在下一行得到token
试试这个
export class GroupsService {
token: any;
constructor(
private storageIonic: NativeStorage,
private env: EnvService,
private http: HttpClient,
) {
// Get token
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
getGroups(): Observable < any > {
// I also add this here to make sure that i will get token in any case, yet it's returning undefined
let response = new Observable<any>();
if (this.token === undefined) {
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
console.log('token: ', this.token); // undefined
const httpOptions = {
headers: new HttpHeaders({
Authorization: this.token, //sending token to server
Accept: 'application/json, text/plain',
'Content-Type': 'application/json'
})
};
response = this.http.get(`${this.env.GROUPS}`, httpOptions).pipe(
map(groups => groups)
);
}).catch(error => console.error(error));
}
return response;
}
}
您可以使用 switchMap
来传输令牌承诺数据。
import { from } from "rxjs";
export class GroupsService {
token: any;
getGroups(): Observable<any> {
// I also add this here to make sure that i will get token in any case, yet it's returning undefined
const tokenPromise =
this.token === undefined
? this.storageIonic.getItem("token")
: Promise.resolve(this.token);
return from(tokenPromise).pipe(
switchMap((token) => {
this.token = token;
const httpOptions = {
headers: new HttpHeaders({
Authorization: this.token, //sending token to server
Accept: "application/json, text/plain",
"Content-Type": "application/json",
}),
};
return this.http
.get(`${this.env.GROUPS}`, httpOptions)
.pipe(map((groups) => groups));
})
);
}
}
在发出 http 请求之前,您需要等待 return 一个值的承诺。您可以将令牌逻辑放入 return 承诺的函数中,然后使用 RxJS from
函数启动可观察对象。一旦承诺 return 成为一个值,您就可以使用 switchMap
发出您的 http 请求。
我已经将你的 map
包含在 RxJS 管道中,尽管它目前什么也没做。
export class GroupsService {
token: any;
constructor(
private storageIonic: NativeStorage,
private env: EnvService,
private http: HttpClient,
) {
}
getGroups(): Observable<any> {
return from(this.getToken()).pipe(
switchMap(() => {
const httpOptions = {
headers: new HttpHeaders({
Authorization : this.token, //sending token to server
Accept: 'application/json, text/plain',
'Content-Type': 'application/json'
})
};
return this.http.get(`${this.env.GROUPS}`, httpOptions);
}),
map(groups => groups)
);
}
private getToken(): Promise<any> {
if (this.token) {
return new Promise((resolve, reject) => resolve(this.token));
}
return this.storageIonic.getItem('token')
.then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
}
我不确定您问题的根源,但您可能希望将您的可观察对象更改为承诺,正如我在评论中所解释的那样。
getGroups(): Promise<any> {
// I also add this here to make sure that i will get token in any case, yet it's returning undefined
if (this.token === undefined) {
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
console.log('token: ', this.token); // undefined
const httpOptions = {
headers: new HttpHeaders({
Authorization : this.token, //sending token to server
Accept: 'application/json, text/plain',
'Content-Type': 'application/json'
})
};
return this.http.get(`${this.env.GROUPS}`, httpOptions).toPromise();
// Also probably the below one works too, you can try to find the proper syntax, it was something like this
return this.http.get(`${this.env.GROUPS}`, httpOptions).pipe(
map(groups => groups)
).toPromise();
}
我改了一些台词。 (更改方法签名,Observable => Promise 并将 toPromise() 添加到 return 行)
您可以像下面这样调用方法。
const response = await getGroups(); // This one will return the response of the request.
If you debug the code you will see that your code will wait here until it gets a response.
// IF YOU DO LIKE BELOW IT WON'T MAKE ANY SENSE
const response = getGroups(); // This will not make the call, it will just return the request object.
// In order to do the operation defined in a promise, you must call it with await prefix.
您可能还需要将上述解决方案应用于代码的其他部分。例如。您正在构造函数下初始化令牌,据我所知这不是一个好习惯,您可能希望将该初始化移动到 onInit() 下并使 onInit 函数异步。通过这种方式,您可以确保在进行调用时定义了令牌,否则在发出请求时您的令牌可能无法初始化。而且由于您没有在未定义检查中等待您的代码,所以同样的事情会再次发生。
(将您的 storageIonic.getItem(token: string) 函数转换为 promise 和 return 来自该函数的令牌)
我有一个服务,我将用户令牌传递给服务器并将 return 结果传递给组件,但是当我的令牌存在时它保持 returning token: undefined
。
代码
Note: I commented each part for better understanding.
Service
export class GroupsService {
token: any;
constructor(
private storageIonic: NativeStorage,
private env: EnvService,
private http: HttpClient,
) {
// Get token
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
getGroups(): Observable<any> {
// I also add this here to make sure that i will get token in any case, yet it's returning undefined
if (this.token === undefined) {
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
console.log('token: ', this.token); // undefined
const httpOptions = {
headers: new HttpHeaders({
Authorization : this.token, //sending token to server
Accept: 'application/json, text/plain',
'Content-Type': 'application/json'
})
};
return this.http.get(`${this.env.GROUPS}`, httpOptions).pipe(
map(groups => groups)
);
}
}
Component
export class Tab1Page implements OnInit {
groups: any[] = [];
groupsOpts = {
loop: false,
slidesPerView: 3,
slidesPerColumn: 2
};
constructor(
private groupsService: GroupsService,
private menu: MenuController,
) {
this.menu.enable(true);
this.getGroups();
}
ngOnInit() {
//
}
// I added async/await yet result hasn't change.
async getGroups() {
await this.groupsService.getGroups().subscribe((res) => {
console.log('res: ', res);
console.log('res data: ', res.data);
console.log('res data data: ', res.data.data);
for (const group of res.data) {
this.groups.push(group);
}
});
}
}
知道如何解决这个问题吗?
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
这个调用是异步的,你不会在下一行得到token 试试这个
export class GroupsService {
token: any;
constructor(
private storageIonic: NativeStorage,
private env: EnvService,
private http: HttpClient,
) {
// Get token
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
getGroups(): Observable < any > {
// I also add this here to make sure that i will get token in any case, yet it's returning undefined
let response = new Observable<any>();
if (this.token === undefined) {
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
console.log('token: ', this.token); // undefined
const httpOptions = {
headers: new HttpHeaders({
Authorization: this.token, //sending token to server
Accept: 'application/json, text/plain',
'Content-Type': 'application/json'
})
};
response = this.http.get(`${this.env.GROUPS}`, httpOptions).pipe(
map(groups => groups)
);
}).catch(error => console.error(error));
}
return response;
}
}
您可以使用 switchMap
来传输令牌承诺数据。
import { from } from "rxjs";
export class GroupsService {
token: any;
getGroups(): Observable<any> {
// I also add this here to make sure that i will get token in any case, yet it's returning undefined
const tokenPromise =
this.token === undefined
? this.storageIonic.getItem("token")
: Promise.resolve(this.token);
return from(tokenPromise).pipe(
switchMap((token) => {
this.token = token;
const httpOptions = {
headers: new HttpHeaders({
Authorization: this.token, //sending token to server
Accept: "application/json, text/plain",
"Content-Type": "application/json",
}),
};
return this.http
.get(`${this.env.GROUPS}`, httpOptions)
.pipe(map((groups) => groups));
})
);
}
}
在发出 http 请求之前,您需要等待 return 一个值的承诺。您可以将令牌逻辑放入 return 承诺的函数中,然后使用 RxJS from
函数启动可观察对象。一旦承诺 return 成为一个值,您就可以使用 switchMap
发出您的 http 请求。
我已经将你的 map
包含在 RxJS 管道中,尽管它目前什么也没做。
export class GroupsService {
token: any;
constructor(
private storageIonic: NativeStorage,
private env: EnvService,
private http: HttpClient,
) {
}
getGroups(): Observable<any> {
return from(this.getToken()).pipe(
switchMap(() => {
const httpOptions = {
headers: new HttpHeaders({
Authorization : this.token, //sending token to server
Accept: 'application/json, text/plain',
'Content-Type': 'application/json'
})
};
return this.http.get(`${this.env.GROUPS}`, httpOptions);
}),
map(groups => groups)
);
}
private getToken(): Promise<any> {
if (this.token) {
return new Promise((resolve, reject) => resolve(this.token));
}
return this.storageIonic.getItem('token')
.then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
}
我不确定您问题的根源,但您可能希望将您的可观察对象更改为承诺,正如我在评论中所解释的那样。
getGroups(): Promise<any> {
// I also add this here to make sure that i will get token in any case, yet it's returning undefined
if (this.token === undefined) {
this.storageIonic.getItem('token').then((token) => {
this.token = token.access_token;
}).catch(error => console.error(error));
}
console.log('token: ', this.token); // undefined
const httpOptions = {
headers: new HttpHeaders({
Authorization : this.token, //sending token to server
Accept: 'application/json, text/plain',
'Content-Type': 'application/json'
})
};
return this.http.get(`${this.env.GROUPS}`, httpOptions).toPromise();
// Also probably the below one works too, you can try to find the proper syntax, it was something like this
return this.http.get(`${this.env.GROUPS}`, httpOptions).pipe(
map(groups => groups)
).toPromise();
}
我改了一些台词。 (更改方法签名,Observable => Promise 并将 toPromise() 添加到 return 行)
您可以像下面这样调用方法。
const response = await getGroups(); // This one will return the response of the request.
If you debug the code you will see that your code will wait here until it gets a response.
// IF YOU DO LIKE BELOW IT WON'T MAKE ANY SENSE
const response = getGroups(); // This will not make the call, it will just return the request object.
// In order to do the operation defined in a promise, you must call it with await prefix.
您可能还需要将上述解决方案应用于代码的其他部分。例如。您正在构造函数下初始化令牌,据我所知这不是一个好习惯,您可能希望将该初始化移动到 onInit() 下并使 onInit 函数异步。通过这种方式,您可以确保在进行调用时定义了令牌,否则在发出请求时您的令牌可能无法初始化。而且由于您没有在未定义检查中等待您的代码,所以同样的事情会再次发生。 (将您的 storageIonic.getItem(token: string) 函数转换为 promise 和 return 来自该函数的令牌)