angular 反应形式值随管道变化。这是一个错误吗???
angular reactive form valuechanges with pipe. IS THIS A BUG ???
似乎管道不适用于反应式表单控件 valueChanges。我已经准备好 https://stackblitz.com/edit/angular-vdeqrz 以便您可以重现该问题。
在文本字段中输入内容。然后键入 "boom"(不带引号)。错误捕获后,控件不再工作。
之后您可以验证在上面输入了一些新内容。它没有检测到任何其他输入。
如果您刷新页面,它会再次运行。
我在这里遗漏了什么吗?
是的,您肯定漏掉了什么。
打开您的控制台(浏览器控制台,而不是 blitz 控制台)并查看您确实遇到错误:
Error: boom
at SwitchMapSubscriber.eval [as project] (app.component.ts:43)
at SwitchMapSubscriber._next (switchMap.ts:100)
at SwitchMapSubscriber.Subscriber.next (Subscriber.ts:102)
at SafeSubscriber.schedulerFn [as _next] (event_emitter.ts:88)
at SafeSubscriber.__tryOrUnsub (Subscriber.ts:270)
at SafeSubscriber.next (Subscriber.ts:212)
at Subscriber._next (Subscriber.ts:142)
at Subscriber.next (Subscriber.ts:102)
at EventEmitter.Subject.next (Subject.ts:62)
at EventEmitter.emit (event_emitter.ts:78)
这就是您的应用程序出现问题的原因。
rxjs throw error operator 将阻止 observable 再次发射,就像您取消订阅 valueChanges observable 一样
像这样尝试使用 throwError 运算符只是抛出新的 Error
对象
this.query.valueChanges
.pipe(map(d => (d === 'boom') ? new Error("boom") : d))
.subscribe(
d => console.log(d),
err => console.log(err),
() => console.log("complete")
)
这不是错误。每个 Rx 流都可以发出零个或多个 next
通知和一个 error
或 complete
通知,但不能同时发出两者。
因此,如果您使用 throwError
链将自行处理,因为您永远不会让同一条链发出两个或多个 error
通知,这正是您所期望的。
显然有很多方法可以避免这种情况。您可以使用不同于 throwError
的东西,例如用某个对象包装输入值。但是你将无法在观察者的 error
处理程序中处理它。
你也可以使用retry
和tap
来处理错误:
this.query.valueChanges
.pipe(
switchMap(d => (d === 'boom') ? throwError(new Error("boom")) : of(d)),
tap({ error: err => console.log(err) }),
retry(),
)
.subscribe({
next: d => console.log(d),
complete: () => console.log("complete")
})
你必须在这里使用 tap
因为错误永远不会到达观察者。
您更新的演示:https://stackblitz.com/edit/angular-1qfn2z?file=src/app/app.component.ts
似乎管道不适用于反应式表单控件 valueChanges。我已经准备好 https://stackblitz.com/edit/angular-vdeqrz 以便您可以重现该问题。
在文本字段中输入内容。然后键入 "boom"(不带引号)。错误捕获后,控件不再工作。 之后您可以验证在上面输入了一些新内容。它没有检测到任何其他输入。
如果您刷新页面,它会再次运行。
我在这里遗漏了什么吗?
是的,您肯定漏掉了什么。
打开您的控制台(浏览器控制台,而不是 blitz 控制台)并查看您确实遇到错误:
Error: boom
at SwitchMapSubscriber.eval [as project] (app.component.ts:43)
at SwitchMapSubscriber._next (switchMap.ts:100)
at SwitchMapSubscriber.Subscriber.next (Subscriber.ts:102)
at SafeSubscriber.schedulerFn [as _next] (event_emitter.ts:88)
at SafeSubscriber.__tryOrUnsub (Subscriber.ts:270)
at SafeSubscriber.next (Subscriber.ts:212)
at Subscriber._next (Subscriber.ts:142)
at Subscriber.next (Subscriber.ts:102)
at EventEmitter.Subject.next (Subject.ts:62)
at EventEmitter.emit (event_emitter.ts:78)
这就是您的应用程序出现问题的原因。
rxjs throw error operator 将阻止 observable 再次发射,就像您取消订阅 valueChanges observable 一样
像这样尝试使用 throwError 运算符只是抛出新的 Error
对象
this.query.valueChanges
.pipe(map(d => (d === 'boom') ? new Error("boom") : d))
.subscribe(
d => console.log(d),
err => console.log(err),
() => console.log("complete")
)
这不是错误。每个 Rx 流都可以发出零个或多个 next
通知和一个 error
或 complete
通知,但不能同时发出两者。
因此,如果您使用 throwError
链将自行处理,因为您永远不会让同一条链发出两个或多个 error
通知,这正是您所期望的。
显然有很多方法可以避免这种情况。您可以使用不同于 throwError
的东西,例如用某个对象包装输入值。但是你将无法在观察者的 error
处理程序中处理它。
你也可以使用retry
和tap
来处理错误:
this.query.valueChanges
.pipe(
switchMap(d => (d === 'boom') ? throwError(new Error("boom")) : of(d)),
tap({ error: err => console.log(err) }),
retry(),
)
.subscribe({
next: d => console.log(d),
complete: () => console.log("complete")
})
你必须在这里使用 tap
因为错误永远不会到达观察者。
您更新的演示:https://stackblitz.com/edit/angular-1qfn2z?file=src/app/app.component.ts