如何在具有嵌套依赖项的嵌套订阅中使用循环?

时间:2019-06-11 13:41:51

标签: node.js angular typescript rxjs subscription

我已经用MEAN(MongoDB,Express,Angular,NodeJS)堆栈构建了一个Web应用程序,想对我的后端进行多个订阅,而第二个订阅则需要第一个订阅的结果数据。

我已经尝试通过代码在其他人的代码中实现其他人的多种解决方案。 flatMap / mergeMap或具有解决承诺的方法,但对我没有任何帮助。我知道显示的带有嵌套订阅的代码不是正确的工作方式。但是,我的HTML代码可以显示交易和帐户md-array中的第一个对象。

transaction.service.ts:

export class TransactionsService {
  private accounts: Account[] = [];
  private account: Account;
  private accountsUpdated = new Subject<{accounts: Account[]}>();
  private transactions: Transaction[] = [];
  private transactionsUpdated = new Subject<{transactions: Transaction[]}>();

  private apiUrl = 'http://localhost:3000/api/accounts';
  private apiUrlBS = 'http://localhost:3000/api/accounts/bs_demo';

  constructor(private http: HttpClient, private router: Router, private as:AuthService) {}

  //Check how many bank account token are in our database
  checkQuantity(userid:string) {    
    return this.http.post(this.apiUrl + "/checkquantity", {userid});
  }

  //Get account data of bankaccount with index (if there are more than one bank account integrated)
  getAccounts(userid: string, index: number) {

    //DataSchema for the http request
    const data = {userid, index};

    //Making a HTTP Request to our Backend with sending out userid and the index of the bankaccount we want
    return this.http.post<{message: string; accounts: any}>(this.apiUrl + "/get", data)
    //Store bankaccounts and subaccounts in local storage
    .subscribe(transformedAccountData => {
        this.accounts = transformedAccountData.accounts;
        this.accountsUpdated.next({accounts: [...this.accounts]});
      })
      , error => {
        console.log('There was an error getting data');
        this.clearToken();
        return Observable.throw(error);
      }

    } 


  //Get transaction data of account with index of chosen bankaccount and the iban (if there is a subaccount)
  getTransactions(transactionsPerPage: number, currentPage: number, iban: string, index:number, userid: string) {
    const headers = new HttpHeaders()
          .set('Authorization', 'my-auth-token')
          .set('Content-Type', 'application/json');

    //Making a HTTP Request to our Backend with sending out iban of account, index of bakaccount and our userid
    return this.http.post<{transactions: any}>(this.apiUrl + "/transactions", {iban, index, userid})
      //Store transactions data of accounts and subaccounts in local storage
      .subscribe(transformedTransactionData => {
        this.transactions = transformedTransactionData.transactions;
        this.transactionsUpdated.next({transactions: [...this.transactions]
        });
      }), error => {
        console.log('There was an error getting data');

        return Observable.throw(error);
      };

  }

  //Listener for list-transactions.component.ts
  getAccountsUpdateListener() {
    return this.accountsUpdated.asObservable();
  }

  //Listener for list-transactions.component.ts
  getTransactionsUpdateListener() {
    return this.transactionsUpdated.asObservable();
  }

list-transactions.component.ts:

export class ListTransactionsComponent implements OnInit {

  accounts : Account[][];
  transactions: Transaction[][];


  totalAccounts = 0;
  userlength;

  isLoading = true;
  tokenerror = false;

  //Not interesting at this time
  totalTransactions = 0;
  transactionsPerPage = 2;
  currentPage = 1;
  pageSizeOptions = [1, 2, 5, 10];

  //counter for our arrays because using the i and j variables does cause errors
  countul = 0;
  countacc = 0;


  constructor(
    public transactionsService: TransactionsService,
    private as: AuthService,
    private router:Router,
    private changeDetectorRefs: ChangeDetectorRef)
  {
        this.accounts = [];
        this.transactions = [];
  }


  //Load accounts and transactions of user

  ngOnInit() {
    //make loading spinner spinning
    this.isLoading = true;

    //check quantity of how many external bank account token we have stored in our database
    this.transactionsService.checkQuantity(this.as.getUserId()).subscribe(accountData => { 
      this.userlength = accountData['length'];

      var countul = 0;
      var countacc = 0;

      //check whether the request was successfull or we have surely one token in our databse
      if(this.userlength === undefined || this.userlength === 0) {
        this.tokenerror = true;
        this.isLoading = false;
      }
      else {

        for(var i = 0; i < this.userlength; i++) {

            try {
              //fetch transactions data of the account with index "countul" to our local storage
              this.transactionsService.getAccounts(this.as.getUserId(), countul);

                //Sort the account data of our specific accounts into our local array
                this.transactionsService.getAccountsUpdateListener().subscribe((pageData: {accounts: Account[], accountsCount: number}) => {

                  this.totalTransactions = pageData.accountsCount;
                  var cache = new Array<Account>();
                  cache = pageData.accounts;
                  this.accounts[countul] = cache;
                  this.isLoading = false;
                  console.log(countul);


                      for(var j = 0; j < this.accounts[countul].length; j++) {

                        //fetch transactions data of the useraccount with index "countul" and subaccount with index "countacc" to our local storage
                        this.transactionsService.getTransactions(this.transactionsPerPage, this.currentPage, this.accounts[countul][countacc].iban, countul, this.as.getUserId());

                        //Printing some things to the console for testing purpose
                        console.log("countacc: "+countacc);
                        console.log(this.accounts[countul][countacc].iban);

                          //Sort the transaction data of our specific accounts into our local array
                          this.transactionsService.getTransactionsUpdateListener()
                          .subscribe((pageData2: {transactions: Transaction[], transactionCount: number}) => {

                            //Saving data in local array
                            this.totalTransactions = pageData2.transactionCount;
                            var cache2 = new Array<Transaction>();
                            cache2 = pageData2.transactions;
                            this.transactions[countacc] = cache2;

                            //Stop loading spinner
                            this.isLoading = false;

                            console.log("Transactions of account " +countacc + ": "+this.transactions[countacc]);

                            //Go to the transactions of the a possible subaccount
                            countacc++;

                          });                       
                        }
                        //Go to the next bankaccount
                        countul++;

              });
              //Stopping the code execution for some time
              setTimeout(()=>{}, 2000);

            } 
            catch (TypeError) {
              //If Token of bankaccount is invalid, delete it
              this.atTokenError();
            }
          }

      }
    }); 
  }


执行此代码的问题在于,我的代码不仅在写数组的第一个索引,而且在for循环仅运行一次槽时写第二个索引。控制台中显示以下内容:

0
list-transactions.component.ts:160 **iban here**
list-transactions.component.ts:163 countacc: 0
list-transactions.component.ts:164 **iban here**
list-transactions.component.ts:178 Trans of acc 0: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

我在这里隐藏了实际的iban。谁能解释一下嵌套嵌套的嵌套订阅的更好的解决方案是什么?

1 个答案:

答案 0 :(得分:0)

@Niklas似乎这里发生了很多事情。您能否详细说明/评论代码或进行Stackblitz?对发生的事情进行更多的澄清将有助于我更有效地帮助您。可以帮助您的一件事是,将多个子订阅推送到订阅数组中比较干净(例如subscriptions.add(thisObservable.subscribe(foo => bar)),这将使取消订阅subscriptions.unsubscribe()更加容易。