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
}