如何更改执行顺序?我有一个数组this.friend
,我需要使用这个数组,但是需要填充数据
this.listUserService.getUsers().subscribe(
async (data: any) => {
this.listUsers = data;
await data.forEach((current: any) => {
if (current.name === userSession) {
this.user = current;
this.friendsService.getFriends(this.user.id).subscribe(response => {
console.log('last', response);//this runs second
this.friends = response;
});
}
});
console.log('friends', this.friends); //friend is clear,
this runs first
this.listUsers = this.listUsers.filter(user => !this.friends.some(relationship => relationship[0].friend.id !== user.id));
}
);
控制台消息以相反的顺序显示,一旦装满,我要如何更改顺序
答案 0 :(得分:2)
没有必要将诺言与可观察变量混合。另外,将subscribe()
方法彼此嵌套也是一个好主意。我建议您使用RxJS运算符处理上述操作。
首先,我们使用mergeMap将服务的getUsers()方法中的可观察值映射到内部可观察值。
然后,我们使用forkJoin等待Array.forEach()
循环完成,然后返回所有可观察值。由于您似乎熟悉JavaScript中Promises的用法,因此它实际上类似于Promise.all
。
最后但并非最不重要的一点,我们在listUsers
块中处理subscribe()
的过滤。这将确保您的异步代码得到正确处理。
this.listUserService.getUsers().pipe(
mergeMap(data => {
this.listUsers = data;
const observablesList = [];
data.forEach((current: any) => {
if (current.name === userSession) {
observablesList.push(this.friendsService.getFriends(current.id));
}
});
return forkJoin(observablesList);
})
).subscribe(response => {
// console.log(response) will give you the returned values from the looped getFriends()
// handle the rest here
});
答案 1 :(得分:1)
您可以尝试使用switchMap,map和tap之类的RxJS运算符来控制可观察对象的流,包括执行诸如设置类属性之类的副作用。
此答案假设在forEach()中只有一个来自if (current.name === userSession) {
的当前用户,随后this.friendsService.getFriends(user.id)
仅执行一次。
import { map, switchMap, tap } from 'rxjs/operators'; // need to import operators
// ...
this.listUserService.getUsers().pipe(
tap(users => this.listUsers = users), // side effect to set this.listUsers
map(users => users.find(user => user.name === userSession)), // find current user
switchMap(user => this.friendsService.getFriends(user.id)), // get friends of current user
tap(friends => this.friends = friends), // side effect to set this.friends
map(friends => this.listUsers.filter(user => this.friends.some(relationship => relationship[0].friend.id !== user.id)))
).subscribe(listUsers => {
this.listUsers = listUsers;
});
您绝对应该查看RxJS文档,以获取更多信息和各种运算符的示例。另外,如果找不到当前用户或任何服务/ api调用失败,您肯定需要改进错误处理。
希望有帮助!
答案 2 :(得分:1)
那是因为您以错误的方式使用RxJS流。您首先设置流,所以其他所有console.log
将首先运行。 Rx流本身是异步的,因此您不需要async await
。另一个console.log
将在实际调用流并接收数据时运行。
RxJS方法是在Rx流中.pipe()
filter()
。
与其说是Angular问题,不如说是与RxJS有关。这是一个看起来像的例子:
this.listUserService
.getUsers()
.pipe(
tap(listUserData => {
this.listUsers = listUserData;
}),
switchMap(data => {
return this.friendsService.getFriends(data.id).pipe(
tap(friends => {
this.friends = friends;
})
);
})
)
.subscribe();
switchMap
切换到另一个可观察的水下,因此您不需要两个订阅。这被认为是好习惯!
我强烈建议您花一些时间学习RxJS,它将使您在Angular中的体验更加有趣和高效!
如果您愿意,我可以帮助您!