布尔值在订阅之外未定义?
Boolean value undefined outside of subscribtion?
我有一个以布尔检查结束的 API 调用。
我想创建新用户,但如果数据库中存在电子邮件,我想设置 canAddUser = false。
我执行以下操作:
canAddUser: boolean;
setNewUserValues() {
if (this.formUser.email) {
this.checkExistingEmail();
}
}
checkExistingEmail() {
this.userService.findPrivilegedUsersUsingGET().subscribe(users => {
const mailIndex = users.findIndex(user => user.email === this.formUser.email);
mailIndex !== -1 ? this.canAddUser = false : this.canAddUser = true;
console.log(this.canAddUser);
});
}
如果我将布尔值记录到我当前正在执行的操作的控制台,我将获得正确的值。但是,如果我在其他地方记录它,它首先是未定义的!然后,如果我触发触发 setNewUserValues() 的按钮,它会再次获得正确的值。
我错过了什么?
编辑
有点解决了我的问题。
setNewUserValues() {
if (this.formUser.email) {
this.checkExistingEmail();
}
}
checkExistingEmail() {
this.userService.findPrivilegedUsersUsingGET().subscribe(users => {
this.mailIndex = users.findIndex(user => user.email === this.formUser.email);
});
this.validateEmail(this.mailIndex);
console.log(this.canAddUser);
}
private validateEmail(index: number) {
index !== -1 ? this.canAddUser = false : this.canAddUser = true;
}
如果我传递了一封现有的电子邮件,我得到了正确的值,但如果我传递了一个不在数据库中的电子邮件,但我首先得到了错误的值,然后如果我再次触发它,那么该值再次正常。
您的 findPrivilegedUsersUsingGET
函数是异步的。这意味着它可能需要几秒钟甚至几分钟才能完成。 canAddUser
只会在异步调用结束时为真或假。
canAddUser: boolean; // undefined
// this can take a while to complete.
this.userService.findPrivilegedUsersUsingGET().subscribe(users => {
const mailIndex = users.findIndex(user => user.email === this.formUser.email);
mailIndex !== -1 ? this.canAddUser = false : this.canAddUser = true;
// do work here
console.log(this.canAddUser);
this.doWork();
});
doWork() {
console.log(this.canAddUser);
}
基本答案,但您可以将 canAddUser
初始化为任何您想要的默认值。
例如 canAddUser = false;
。
如果您不订阅异步操作,则无法保证您的标志已分配给代码中的任何位置。
我要做的是将布尔标志更改为主题:
canAddUser$: Subject<boolean>;
在需要时发出值:
mailIndex !== -1 ? this.canAddUser$.next(false): this.canAddUser$.next(true);
// this.canAddUser$.next(mailIndex === -1);
当你需要的时候,订阅它:
someFunction() {
this.canAddUser$.subscribe(canAdd => {
// Here *canAdd* is a boolean
})
}
您可以预先加载用户列表,然后通过模板将用户传递给组件的功能。
在你的组件中:
public users$: Observable<any[]>;
public ngOnInit() {
this.users$ = this.userService.findPrivilegedUsersUsingGET().pipe(share());
}
setNewUserValues(users: any[]) {
if (this.formUser.email) {
this.checkExistingEmail(users);
}
}
checkExistingEmail(users: any[]) {
this.mailIndex = users.findIndex(user => user.email === this.formUser.email);
this.validateEmail(this.mailIndex);
console.log(this.canAddUser);
}
private validateEmail(index: number) {
index !== -1 ? this.canAddUser = false : this.canAddUser = true;
}
在您的模板中:
<ng-container *ngIf="users$ | async as users">
<button (click)="setNewUserValues(users)">Example</button>
</ng-container>
<ng-container *ngIf"!(users$ | async">
Loading users...
</ng-container>
这是消除混合过程式编程和反应式编程的副作用的一种方法。
另一种方法是使 checkExistingEmail()
return 成为可观察对象(或 Promise)。
public constructor(private _change: ChangeDetectorRef) {}
setNewUserValues() {
if (this.formUser.email) {
this.checkExistingEmail(this.formUser.email).subscribe(canAddUser => {
console.log("canAddUser:", canAddUser);
this.canAddUser = canAddUser;
this._change.markForCheck();
});
}
}
public checkExistingEmail(email): Observable<boolean> {
return this.userService.findPrivilegedUsersUsingGET().pipe(
map(users => users.findIndex(user => user.email === email) !== -1)
);
}
上面将布尔结果打印到控制台,但我不知道你想用这个结果做什么。操作异步完成,我们需要告诉 Angular 组件的状态已经改变,视图应该更新所以我调用 "markForCheck()",但是如果你没有使用 OnPush
更改检测,那么这可能不是必需的。
作为一般规则。如果您在组件内部的异步回调中编写类似 this.XXXX = YYYY;
的代码。您将 运行 引入副作用,因为您将过程式编程与反应式编程混合在一起。
人们经常会问这个问题"how do I return a value from an async function"。当我看到他们的示例源代码使用 this
引用更新 属性.
时,我经常 畏缩
进一步阅读有关响应式编程的一些内容可能会有所帮助:
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
https://egghead.io/courses/introduction-to-reactive-programming
最好在 Angular:
中复习反应形式的主题
我有一个以布尔检查结束的 API 调用。 我想创建新用户,但如果数据库中存在电子邮件,我想设置 canAddUser = false。 我执行以下操作:
canAddUser: boolean;
setNewUserValues() {
if (this.formUser.email) {
this.checkExistingEmail();
}
}
checkExistingEmail() {
this.userService.findPrivilegedUsersUsingGET().subscribe(users => {
const mailIndex = users.findIndex(user => user.email === this.formUser.email);
mailIndex !== -1 ? this.canAddUser = false : this.canAddUser = true;
console.log(this.canAddUser);
});
}
如果我将布尔值记录到我当前正在执行的操作的控制台,我将获得正确的值。但是,如果我在其他地方记录它,它首先是未定义的!然后,如果我触发触发 setNewUserValues() 的按钮,它会再次获得正确的值。 我错过了什么?
编辑
有点解决了我的问题。
setNewUserValues() {
if (this.formUser.email) {
this.checkExistingEmail();
}
}
checkExistingEmail() {
this.userService.findPrivilegedUsersUsingGET().subscribe(users => {
this.mailIndex = users.findIndex(user => user.email === this.formUser.email);
});
this.validateEmail(this.mailIndex);
console.log(this.canAddUser);
}
private validateEmail(index: number) {
index !== -1 ? this.canAddUser = false : this.canAddUser = true;
}
如果我传递了一封现有的电子邮件,我得到了正确的值,但如果我传递了一个不在数据库中的电子邮件,但我首先得到了错误的值,然后如果我再次触发它,那么该值再次正常。
您的 findPrivilegedUsersUsingGET
函数是异步的。这意味着它可能需要几秒钟甚至几分钟才能完成。 canAddUser
只会在异步调用结束时为真或假。
canAddUser: boolean; // undefined
// this can take a while to complete.
this.userService.findPrivilegedUsersUsingGET().subscribe(users => {
const mailIndex = users.findIndex(user => user.email === this.formUser.email);
mailIndex !== -1 ? this.canAddUser = false : this.canAddUser = true;
// do work here
console.log(this.canAddUser);
this.doWork();
});
doWork() {
console.log(this.canAddUser);
}
基本答案,但您可以将 canAddUser
初始化为任何您想要的默认值。
canAddUser = false;
。
如果您不订阅异步操作,则无法保证您的标志已分配给代码中的任何位置。
我要做的是将布尔标志更改为主题:
canAddUser$: Subject<boolean>;
在需要时发出值:
mailIndex !== -1 ? this.canAddUser$.next(false): this.canAddUser$.next(true);
// this.canAddUser$.next(mailIndex === -1);
当你需要的时候,订阅它:
someFunction() {
this.canAddUser$.subscribe(canAdd => {
// Here *canAdd* is a boolean
})
}
您可以预先加载用户列表,然后通过模板将用户传递给组件的功能。
在你的组件中:
public users$: Observable<any[]>;
public ngOnInit() {
this.users$ = this.userService.findPrivilegedUsersUsingGET().pipe(share());
}
setNewUserValues(users: any[]) {
if (this.formUser.email) {
this.checkExistingEmail(users);
}
}
checkExistingEmail(users: any[]) {
this.mailIndex = users.findIndex(user => user.email === this.formUser.email);
this.validateEmail(this.mailIndex);
console.log(this.canAddUser);
}
private validateEmail(index: number) {
index !== -1 ? this.canAddUser = false : this.canAddUser = true;
}
在您的模板中:
<ng-container *ngIf="users$ | async as users">
<button (click)="setNewUserValues(users)">Example</button>
</ng-container>
<ng-container *ngIf"!(users$ | async">
Loading users...
</ng-container>
这是消除混合过程式编程和反应式编程的副作用的一种方法。
另一种方法是使 checkExistingEmail()
return 成为可观察对象(或 Promise)。
public constructor(private _change: ChangeDetectorRef) {}
setNewUserValues() {
if (this.formUser.email) {
this.checkExistingEmail(this.formUser.email).subscribe(canAddUser => {
console.log("canAddUser:", canAddUser);
this.canAddUser = canAddUser;
this._change.markForCheck();
});
}
}
public checkExistingEmail(email): Observable<boolean> {
return this.userService.findPrivilegedUsersUsingGET().pipe(
map(users => users.findIndex(user => user.email === email) !== -1)
);
}
上面将布尔结果打印到控制台,但我不知道你想用这个结果做什么。操作异步完成,我们需要告诉 Angular 组件的状态已经改变,视图应该更新所以我调用 "markForCheck()",但是如果你没有使用 OnPush
更改检测,那么这可能不是必需的。
作为一般规则。如果您在组件内部的异步回调中编写类似 this.XXXX = YYYY;
的代码。您将 运行 引入副作用,因为您将过程式编程与反应式编程混合在一起。
人们经常会问这个问题"how do I return a value from an async function"。当我看到他们的示例源代码使用 this
引用更新 属性.
进一步阅读有关响应式编程的一些内容可能会有所帮助:
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
https://egghead.io/courses/introduction-to-reactive-programming
最好在 Angular:
中复习反应形式的主题