Tìm kiếm trang web

angular - RxJs: forkJoin() không chạy vì danh sách observables của tôi chưa đầy đủ


Chà, tôi có một vấn đề mà tôi không thể giải quyết.

Tôi đang duyệt một danh sách dữ liệu từ một tệp XLSX. Đối với mỗi dòng của tệp, hai yêu cầu được gửi đến máy chủ:

  • Một để khôi phục kỳ
  • Một cách khác để khôi phục người dùng

Một ví có thể quan sát được được tạo ra để lưu trữ phần dữ liệu còn lại trong dòng. Nó được hoàn tất ngay sau đó. Nếu không, vòng lặp sẽ tiếp tục thực thi và dữ liệu cuối cùng trong danh sách sẽ được tính đến trong forkjoin().

Vì vậy tôi sử dụng forkJoin() để chờ kết quả của ba observable vẫn đang trong vòng lặp. Khi ba observable đã hoàn thành, một yêu cầu mới được gửi đi. Và chính ở đây đã làm anh ấy bị tắc. Truy vấn mới được thêm vào danh sách các observable.

Và tôi muốn chạy phần còn lại của mã chỉ sau khi danh sách các observable của tôi hoàn tất bằng cách sử dụng forkJoin() một lần nữa, sau khi duyệt dữ liệu từ tệp XLSX. Vấn đề là vòng lặp của tôi duyệt qua tệp kết thúc trước khi danh sách observable của tôi chứa bất cứ thứ gì, và forkJoin() thứ hai không bao giờ được thực thi.

MÃ :

for(var objectives of this.XLSXObjectives) {
    if(objectives.values != 0) {
        // 2 requests (period and user)
        var period$ = this.storePeriods.getPeriod(new Period({month: objectives.values[0].month, year: objectives.values[0].year}));
        var user$ = this.storeUsers.getUser(new User({num_seller: objectives.values[0].userCode}));

        // Observable (wallet)
        var XLSXWalletSubject: BehaviorSubject<Wallet> = new BehaviorSubject<Wallet>(null);
        var XLSXWallet$: Observable<any> = XLSXWalletSubject.asObservable();
        XLSXWalletSubject.next(new Wallet({
            wallet_name: objectives.values[0].walletName,
            user: null,
            period: null,
            margin_m: 0,
            value_100: objectives.values[0].ValueAt100Percent,
            percentage_100_m: 0
        }));

        // Wait for the result of the three observables
        forkJoin(period$, user$, XLSXWallet$).subscribe(
            ([period, user, wallet]) => {
                console.warn("OK!");

                wallet.period = period;
                wallet.user = user;

                // New request
                var wallet$ = this.storeObjectives.addXLSXWallet(wallet);
                // Request is added to a list of observables
                this.observables$.push(wallet$);

                wallet$.subscribe(w => { ... });
            }
        );
        // Observable (wallet) complete
        XLSXWalletSubject.complete();
    }
}

console.warn(this.observables$); // this.observables$ = []
forkJoin(this.observables$).subscribe(results => {
    console.log("It doesn't work!!!")
});

Nếu ai có giải pháp giúp tôi, cảm ơn.

Câu trả lời #1

Tôi không chắc chắn 100% về điều này, nhưng tôi nghĩ những gì bạn cần là một thứ gì đó kiểu như sau:

from(this.XLSXObjectives).pipe(
  filter(objectives => objectives.values != 0),
  mergeMap(objectives => forkJoin(
    this.storePeriods.getPeriod(new Period({month: objectives.values[0].month, year: objectives.values[0].year}),
    this.storeUsers.getUser(new User({num_seller: objectives.values[0].userCode}),
    of(new Wallet({
      wallet_name: objectives.values[0].walletName,
      user: null,
      period: null,
      margin_m: 0,
      value_100: objectives.values[0].ValueAt100Percent,
      percentage_100_m: 0
    }))
  )),
  map(([period, user, wallet]) => ({ ...wallet, period, user})),
  mergeMap(wallet => this.storeObjectives.addXLSXWallet(wallet)),
  toArray()
).subscribe(results => { // handle array of results here });
  • các mục tiêu được phát ra từng cái một
  • the mergeMap đăng ký vào forkJoin của ba Observable bên trong của bạn (nếu bạn cần các yêu cầu được xử lý từng cái một, hãy sử dụng concatMap, và nếu bạn chỉ muốn một số lượng nhất định các yêu cầu đồng thời, hãy thêm một đối số concurrency vào mergeMap)
  • lệnh map điền vào đối tượng wallet của bạn với period: period và user: user
  • mergeMap cuối cùng thực hiện yêu cầu tiếp theo sử dụng đối tượng wallet
  • lời gọi toArray chờ đến khi toàn bộ Observable hoàn tất và phát ra tất cả các giá trị đã nhận dưới dạng một mảng