如何使用 BehaviorSubject 值作为方法的参数?
How to use BehaviorSubject value as an argument for a method?
我正在使用 BehaviorSubject 来保存与其他组件共享的变量(用户名),它在我的模板上显示用户名时效果很好。但是,我希望能够在服务中使用我的 BehaviorSubject 的值,然后将该值(用户名)用作如下方法的参数:myMethod(username){ do stuff }。
问题似乎是在调用该方法时 BehaviorSubject 值尚未准备好。我已经尝试在构造函数和 ngOnInIt 中调用该方法,如果我将它记录到控制台,它会显示起初它是未定义的,然后最终它会使用正确的(用户名)值进行记录。是否可以使用 BehaviorSubject 获取作为参数传递给方法的值?
在我的例子中,我有一个 auth.service,它有我的 BehaviorSubject(没有显示 login/auth 的东西,因为它与这个例子无关)。然后在我的 newform.component.ts 中订阅了该 BehaviorSubject。我可以在 newform 模板上显示值,但这不是我想要做的。
我正在努力解决的问题是订阅 newform.component 中的 BehaviorSubject 值并将其传递给调用服务的方法,该服务应该 return 基于用户名的位置数组。我需要那个位置数组来填充新表单模板上的输入,这就是为什么我试图在 ngOnInIt 上调用它...所以我可以在用户开始填写表单之前获取输入的位置。
下面是一些代码:
auth.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private accountInfoSource = new BehaviorSubject<any>({});
accountInfoCurrent = this.accountInfoSource.asObservable();
constructor() { }
accountInfoChange(accountName: any) {
this.accountInfoSource.next(accountName)
}
}
newform.component.ts
import { Component, OnInit } from '@angular/core';
import { Locationslist } from '../services/locationslist.service';
import { AuthService } from '../services/auth.service';
@Component({
selector: 'app-new-charge',
templateUrl: './new-charge.component.html',
styleUrls: ['./new-charge.component.css']
})
export class NewChargeComponent implements OnInit {
accountName: string;
locations;
constructor(protected authService: AuthService, private locations: Locationslist) { }
ngOnInit() {
this.getLocations();
}
getLocations() {
this.authService.accountInfoCurrent.subscribe(accountInfo => {
this.accountName = accountInfo.AccountName;
} );
this.locations.getUserLocations(this.accountName) // <=== this.accountName is undefined
.subscribe(foundset => {
this.locations = foundset;
});
}
}
locationslist.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class Valuelists {
constructor(private http: HttpClient, protected authService: AuthService) { }
getUserLocations(accountname) {
let token = localStorage.getItem('token');
let body = '{\"query\": [ { \"AccountName\" : \"=' + accountname + '\"} ] }';
const findLocations = 'https://my.api';
let auth = 'Bearer ' + token;
return this.http.post(findLocations, body, {
headers: new HttpHeaders()
.set('Content-Type', 'application/json')
.set('Access-Control-Allow-Origin', '*')
.set('Authorization', auth)
})
}
}
我知道如果我将 "accountname" 硬编码到 getUserLocations(accountname) 的参数中,locationslist 服务就可以工作。事实上,locationservice 最终与 BehaviorSubject 值一起工作,但在控制台中,我首先看到 500 的 http 响应错误,然后我最终获得了位置信息。再一次,似乎 BehaviorSubject 变量出现得很晚。有没有办法将 BehaviorSubject 值作为参数传递给方法,或者有更好的方法来实现我的目标?
当然,您只需要在函数本身中使用反应式方法。
name$: BehaviorSubject<string> = new BehaviorSubject("");
function doSomething() {
this.name$.subscribe(console.log); // Here you have that name
// You can filter it like (.pipe(filter(name => !!name)) is you don't want undefined value
}
// Your location function would look like this:
function getLocations() {
this.name$.pipe(switchMap(name => { // Every time name subject changes, switch to another getUserLocations
return this.locations.getUserLocations(name)
}))
.subscribe(foundset => {
this.locations = foundset;
});
}
像上面的函数一样为 getLocations
函数删除未定义的值。
在这种情况下,你应该看看Resolve Guard。这样做的目的是在加载组件之前预取一些数据。从您的问题来看,您似乎首先需要组件中的用户名,然后再执行其余功能。
创建 resolve guard 的基本步骤是
创建一个获取用户名的服务
通过调用您的服务
创建一个 resolve guard,它实现了 return 可观察对象的 resolve
方法
在该组件的路由配置中添加 resolve guard 的引用
在您的组件中,订阅组件数据参数并获取用户名
请注意,路由配置中的一个组件可以有多个解析守卫。
https://www.concretepage.com/angular-2/angular-resolve-guard-example
提供了一个很好的例子
你需要连接这两个方法,让第二个等待第一个完成。
您可以使用 map
运算符来实现,只需将第二个函数放在 map
函数中即可。
getLocations() {
this.authService.accountInfoCurrent.pipe(map(() => {
this.locations.getUserLocations(this.accountName)
.subscribe(foundset => {
this.locations = foundset;
});
})).subscribe(accountInfo => {
this.accountName = accountInfo.AccountName;
} );
}
感谢大家的投入和帮助。我最终使用路由参数将数据从一个组件发送到下一个组件。它更直接,更可能是 "proper" 将 "parameter" 传递给另一个组件的方式(因此得名路由参数!)。它也不是异步的,因此您不必为 BehaviorSubject 可观察对象 "wait"。可以直接加载OnInIt.
希望对您有所帮助!
使用 angular 12 你可以添加 null 或 undefined!:
subjectUser:BehaviorSubject<User> = new BehaviorSubject<User>(null!);
我正在使用 BehaviorSubject 来保存与其他组件共享的变量(用户名),它在我的模板上显示用户名时效果很好。但是,我希望能够在服务中使用我的 BehaviorSubject 的值,然后将该值(用户名)用作如下方法的参数:myMethod(username){ do stuff }。
问题似乎是在调用该方法时 BehaviorSubject 值尚未准备好。我已经尝试在构造函数和 ngOnInIt 中调用该方法,如果我将它记录到控制台,它会显示起初它是未定义的,然后最终它会使用正确的(用户名)值进行记录。是否可以使用 BehaviorSubject 获取作为参数传递给方法的值?
在我的例子中,我有一个 auth.service,它有我的 BehaviorSubject(没有显示 login/auth 的东西,因为它与这个例子无关)。然后在我的 newform.component.ts 中订阅了该 BehaviorSubject。我可以在 newform 模板上显示值,但这不是我想要做的。 我正在努力解决的问题是订阅 newform.component 中的 BehaviorSubject 值并将其传递给调用服务的方法,该服务应该 return 基于用户名的位置数组。我需要那个位置数组来填充新表单模板上的输入,这就是为什么我试图在 ngOnInIt 上调用它...所以我可以在用户开始填写表单之前获取输入的位置。
下面是一些代码:
auth.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private accountInfoSource = new BehaviorSubject<any>({});
accountInfoCurrent = this.accountInfoSource.asObservable();
constructor() { }
accountInfoChange(accountName: any) {
this.accountInfoSource.next(accountName)
}
}
newform.component.ts
import { Component, OnInit } from '@angular/core';
import { Locationslist } from '../services/locationslist.service';
import { AuthService } from '../services/auth.service';
@Component({
selector: 'app-new-charge',
templateUrl: './new-charge.component.html',
styleUrls: ['./new-charge.component.css']
})
export class NewChargeComponent implements OnInit {
accountName: string;
locations;
constructor(protected authService: AuthService, private locations: Locationslist) { }
ngOnInit() {
this.getLocations();
}
getLocations() {
this.authService.accountInfoCurrent.subscribe(accountInfo => {
this.accountName = accountInfo.AccountName;
} );
this.locations.getUserLocations(this.accountName) // <=== this.accountName is undefined
.subscribe(foundset => {
this.locations = foundset;
});
}
}
locationslist.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class Valuelists {
constructor(private http: HttpClient, protected authService: AuthService) { }
getUserLocations(accountname) {
let token = localStorage.getItem('token');
let body = '{\"query\": [ { \"AccountName\" : \"=' + accountname + '\"} ] }';
const findLocations = 'https://my.api';
let auth = 'Bearer ' + token;
return this.http.post(findLocations, body, {
headers: new HttpHeaders()
.set('Content-Type', 'application/json')
.set('Access-Control-Allow-Origin', '*')
.set('Authorization', auth)
})
}
}
我知道如果我将 "accountname" 硬编码到 getUserLocations(accountname) 的参数中,locationslist 服务就可以工作。事实上,locationservice 最终与 BehaviorSubject 值一起工作,但在控制台中,我首先看到 500 的 http 响应错误,然后我最终获得了位置信息。再一次,似乎 BehaviorSubject 变量出现得很晚。有没有办法将 BehaviorSubject 值作为参数传递给方法,或者有更好的方法来实现我的目标?
当然,您只需要在函数本身中使用反应式方法。
name$: BehaviorSubject<string> = new BehaviorSubject("");
function doSomething() {
this.name$.subscribe(console.log); // Here you have that name
// You can filter it like (.pipe(filter(name => !!name)) is you don't want undefined value
}
// Your location function would look like this:
function getLocations() {
this.name$.pipe(switchMap(name => { // Every time name subject changes, switch to another getUserLocations
return this.locations.getUserLocations(name)
}))
.subscribe(foundset => {
this.locations = foundset;
});
}
像上面的函数一样为 getLocations
函数删除未定义的值。
在这种情况下,你应该看看Resolve Guard。这样做的目的是在加载组件之前预取一些数据。从您的问题来看,您似乎首先需要组件中的用户名,然后再执行其余功能。
创建 resolve guard 的基本步骤是
创建一个获取用户名的服务
通过调用您的服务
创建一个 resolve guard,它实现了 return 可观察对象的 在该组件的路由配置中添加 resolve guard 的引用
在您的组件中,订阅组件数据参数并获取用户名
resolve
方法
请注意,路由配置中的一个组件可以有多个解析守卫。
https://www.concretepage.com/angular-2/angular-resolve-guard-example
提供了一个很好的例子你需要连接这两个方法,让第二个等待第一个完成。
您可以使用 map
运算符来实现,只需将第二个函数放在 map
函数中即可。
getLocations() {
this.authService.accountInfoCurrent.pipe(map(() => {
this.locations.getUserLocations(this.accountName)
.subscribe(foundset => {
this.locations = foundset;
});
})).subscribe(accountInfo => {
this.accountName = accountInfo.AccountName;
} );
}
感谢大家的投入和帮助。我最终使用路由参数将数据从一个组件发送到下一个组件。它更直接,更可能是 "proper" 将 "parameter" 传递给另一个组件的方式(因此得名路由参数!)。它也不是异步的,因此您不必为 BehaviorSubject 可观察对象 "wait"。可以直接加载OnInIt.
希望对您有所帮助!
使用 angular 12 你可以添加 null 或 undefined!:
subjectUser:BehaviorSubject<User> = new BehaviorSubject<User>(null!);