Angular 11:尝试使用 combineLatest 为对象赋值
Angular 11: trying to assign values to an object using combineLatest
我整天都在为此苦苦挣扎。我有一个具有名为 Invoice 接口的组件,我需要为某些字段分配值,以便我可以将发票对象传递给服务以保存到数据库。我通常更命令式地编程,但试图在这个新组件中更具声明性。
在我的组件中,我有一些流,我正在尝试合并最新的流,然后我需要从合并的流中获取值并分配:
private newInvoice = {} as Invoice;
invoiceBatch$ = this.invoiceBatchService.invoiceBatch$;
nextInvoiceNumber$ = this.invoiceBatchService.newInvoiceNumberAction$;
ngOnInit() {
combineLatest([
this.nextInvoiceNumber$,
this.invoiceBatch$,
this.userService.currentUser$]
).subscribe(res => {
this.newInvoice.InvoiceBatchID = res[1].InvoiceBatchID;
this.newInvoice.FiscYearPer = res[1].FiscYearPer;
this.newInvoice.InvoiceNumber = res[0];
this.newInvoice.CreatedByID = +res[2].ApplicationUserID;
this.newInvoice.CreatedBy = res[2].UserName;
})
}
createNextInvoice(){
this.invoiceBatchService.getNextInvoiceNumber();
}
在我的模板中,用户单击一个按钮以添加新发票并触发 createNextInvoice() 方法。此方法调用外出的服务并获取下一个发票编号。
发票批量服务
private newInvoiceNumberSubject = new Subject<string>();
private invoiceNumberDataStore: { invoicenumber: string } = { invoicenumber: null};
readonly newInvoiceNumberAction$ = this.newInvoiceNumberSubject.asObservable();
public getNextInvoiceNumber() {
return this.http.get<string>(this.baseUrl + `/batch/GetNextReferenceNumber/9`)
.subscribe(
data => {
this.invoiceNumberDataStore.invoicenumber = data;
this.newInvoiceNumberSubject.next(Object.assign({}, this.invoiceNumberDataStore).invoicenumber);
console.log("NewInvoice: ", data);
}, error => {
}
);
}
我的想法是,当调用 'createNextInvoice()' 时,它会获取下一个发票编号并更新 nextInvoiceNumber$。 combineLastest 不应该对 nextInvoiceNumber$ 的变化做出反应吗?订阅错了吗?我尝试了很多与 map、mergeMap、switchMap 等的组合
invoiceBatch$ 和 this.userService.currentUser$ 在创建组件时设置一次因此 nextInvoiceNumber$ 是唯一会根据用户操作更新的内容。
更新
我离得更近了。我可以为对象赋值,但每次添加新发票时它都会触发两次。进步了!
我在我的组件中做了这些更改:
newInvoice$ = combineLatest([
this.nextInvoiceNumber$,
this.invoiceBatch$,
this.userService.currentUser$]
);
ngOnInit() {
this.newInvoice$.
subscribe(res => {
this.newInvoice.fdInvoiceNumber = res[0];
this.newInvoice.fdInvoiceBatchID = res[1].fdInvoiceBatchID;
this.newInvoice.fdFiscYearPer = res[1].fdFiscYearPer;
this.newInvoice.fdCreatedByID = +res[2].fdApplicationUserID;
this.newInvoice.fdCreatedBy = res[2].fdUserName;
this.invoiceService.CreateInvoice(this.newInvoice);
});
不太确定您的情况如何,但这是您的代码的超级简化版本。您可以自己复制并运行。运行正常。
由于您还没有真正告诉我们您期望发生什么,因此很难进行比这更深入的调试。
// Declare a global that gets sets in a subscribe block later
let newInvoice = {};
// Declare a subject that we can .next whenever to trigger a combine latest
const nextInvoiceNumber$ = new Subject<string>();
// combine latest with the gives subject and two other simple 1-emission
// observables
combineLatest([
nextInvoiceNumber$,
of({InvoiceBatchID: 1111, FiscYearPer: 1234}),
of({ApplicationUserID: 4321, UserName: "Tommy"})
]).subscribe(
( [InvoiceNumber,
{InvoiceBatchID, FiscYearPer},
{ApplicationUserID, UserName}
]) => {
// Give the global declare earlier a new value
newInvoice = {
...newInvoice,
InvoiceNumber,
InvoiceBatchID,
FiscYearPer,
CreatedByID: ApplicationUserID,
CreatedBy: UserName
};
// Log the new value just to see what's up
console.log(newInvoice);
}
);
// getNextInvoiceNumber returns a subscption and not an InvoiceNumber
// We could generate a random invoice number to mimic an api call, but
// we'll just pass one in for brevity
function getNextInvoiceNumber(invoiceNumber) {
// Pretend timer is an api call like this.http.get
return timer(3000).subscribe(_ => {
// Somewhre in the subscribe, call .next on a subject
nextInvoiceNumber$.next(invoiceNumber);
})
}
// Pretend we getNextInvoiceNumber 3 times with different invoices each time
// Ignore the return value of getNextInvoiceNumber
getNextInvoiceNumber("1872");
getNextInvoiceNumber("1986");
getNextInvoiceNumber("2010");
这是输出;正如预期的那样,只有发票编号发生变化:
{ CreatedBy: "Tommy"
, CreatedByID: 4321
, FiscYearPer: 1234
, InvoiceBatchID: 1111
, InvoiceNumber: "1872"
, __proto__: Object
}
{ CreatedBy: "Tommy"
, CreatedByID: 4321
, FiscYearPer: 1234
, InvoiceBatchID: 1111
, InvoiceNumber: "1986"
, __proto__: Object
}
{ CreatedBy: "Tommy"
, CreatedByID: 4321
, FiscYearPer: 1234
, InvoiceBatchID: 1111
, InvoiceNumber: "2010"
, __proto__: Object
}
我整天都在为此苦苦挣扎。我有一个具有名为 Invoice 接口的组件,我需要为某些字段分配值,以便我可以将发票对象传递给服务以保存到数据库。我通常更命令式地编程,但试图在这个新组件中更具声明性。
在我的组件中,我有一些流,我正在尝试合并最新的流,然后我需要从合并的流中获取值并分配:
private newInvoice = {} as Invoice;
invoiceBatch$ = this.invoiceBatchService.invoiceBatch$;
nextInvoiceNumber$ = this.invoiceBatchService.newInvoiceNumberAction$;
ngOnInit() {
combineLatest([
this.nextInvoiceNumber$,
this.invoiceBatch$,
this.userService.currentUser$]
).subscribe(res => {
this.newInvoice.InvoiceBatchID = res[1].InvoiceBatchID;
this.newInvoice.FiscYearPer = res[1].FiscYearPer;
this.newInvoice.InvoiceNumber = res[0];
this.newInvoice.CreatedByID = +res[2].ApplicationUserID;
this.newInvoice.CreatedBy = res[2].UserName;
})
}
createNextInvoice(){
this.invoiceBatchService.getNextInvoiceNumber();
}
在我的模板中,用户单击一个按钮以添加新发票并触发 createNextInvoice() 方法。此方法调用外出的服务并获取下一个发票编号。
发票批量服务
private newInvoiceNumberSubject = new Subject<string>();
private invoiceNumberDataStore: { invoicenumber: string } = { invoicenumber: null};
readonly newInvoiceNumberAction$ = this.newInvoiceNumberSubject.asObservable();
public getNextInvoiceNumber() {
return this.http.get<string>(this.baseUrl + `/batch/GetNextReferenceNumber/9`)
.subscribe(
data => {
this.invoiceNumberDataStore.invoicenumber = data;
this.newInvoiceNumberSubject.next(Object.assign({}, this.invoiceNumberDataStore).invoicenumber);
console.log("NewInvoice: ", data);
}, error => {
}
);
}
我的想法是,当调用 'createNextInvoice()' 时,它会获取下一个发票编号并更新 nextInvoiceNumber$。 combineLastest 不应该对 nextInvoiceNumber$ 的变化做出反应吗?订阅错了吗?我尝试了很多与 map、mergeMap、switchMap 等的组合
invoiceBatch$ 和 this.userService.currentUser$ 在创建组件时设置一次因此 nextInvoiceNumber$ 是唯一会根据用户操作更新的内容。
更新
我离得更近了。我可以为对象赋值,但每次添加新发票时它都会触发两次。进步了!
我在我的组件中做了这些更改:
newInvoice$ = combineLatest([
this.nextInvoiceNumber$,
this.invoiceBatch$,
this.userService.currentUser$]
);
ngOnInit() {
this.newInvoice$.
subscribe(res => {
this.newInvoice.fdInvoiceNumber = res[0];
this.newInvoice.fdInvoiceBatchID = res[1].fdInvoiceBatchID;
this.newInvoice.fdFiscYearPer = res[1].fdFiscYearPer;
this.newInvoice.fdCreatedByID = +res[2].fdApplicationUserID;
this.newInvoice.fdCreatedBy = res[2].fdUserName;
this.invoiceService.CreateInvoice(this.newInvoice);
});
不太确定您的情况如何,但这是您的代码的超级简化版本。您可以自己复制并运行。运行正常。
由于您还没有真正告诉我们您期望发生什么,因此很难进行比这更深入的调试。
// Declare a global that gets sets in a subscribe block later
let newInvoice = {};
// Declare a subject that we can .next whenever to trigger a combine latest
const nextInvoiceNumber$ = new Subject<string>();
// combine latest with the gives subject and two other simple 1-emission
// observables
combineLatest([
nextInvoiceNumber$,
of({InvoiceBatchID: 1111, FiscYearPer: 1234}),
of({ApplicationUserID: 4321, UserName: "Tommy"})
]).subscribe(
( [InvoiceNumber,
{InvoiceBatchID, FiscYearPer},
{ApplicationUserID, UserName}
]) => {
// Give the global declare earlier a new value
newInvoice = {
...newInvoice,
InvoiceNumber,
InvoiceBatchID,
FiscYearPer,
CreatedByID: ApplicationUserID,
CreatedBy: UserName
};
// Log the new value just to see what's up
console.log(newInvoice);
}
);
// getNextInvoiceNumber returns a subscption and not an InvoiceNumber
// We could generate a random invoice number to mimic an api call, but
// we'll just pass one in for brevity
function getNextInvoiceNumber(invoiceNumber) {
// Pretend timer is an api call like this.http.get
return timer(3000).subscribe(_ => {
// Somewhre in the subscribe, call .next on a subject
nextInvoiceNumber$.next(invoiceNumber);
})
}
// Pretend we getNextInvoiceNumber 3 times with different invoices each time
// Ignore the return value of getNextInvoiceNumber
getNextInvoiceNumber("1872");
getNextInvoiceNumber("1986");
getNextInvoiceNumber("2010");
这是输出;正如预期的那样,只有发票编号发生变化:
{ CreatedBy: "Tommy"
, CreatedByID: 4321
, FiscYearPer: 1234
, InvoiceBatchID: 1111
, InvoiceNumber: "1872"
, __proto__: Object
}
{ CreatedBy: "Tommy"
, CreatedByID: 4321
, FiscYearPer: 1234
, InvoiceBatchID: 1111
, InvoiceNumber: "1986"
, __proto__: Object
}
{ CreatedBy: "Tommy"
, CreatedByID: 4321
, FiscYearPer: 1234
, InvoiceBatchID: 1111
, InvoiceNumber: "2010"
, __proto__: Object
}