在 Angular 中调用服务后,数据未显示在 NG Bootstrap table 中

Data is not showing in NG Bootstrap table after calling a service in Angular

我正在使用 Angular Bootstrap library to develop my application. I have used the Angular Bootstrap Table to create a page to show some information which is sortable and searchable. So I have followed this link

以下服务具有调用 API 获取数据的代码。我可以将数据打印到控制台中。但是每当我在我的组件中调用服务时,数据都不会显示在我的组件中。

服务:

interface SearchResultUserRegistrationInfo {
    userLists: UserRegistrationInfo[];
    total: number;
}

interface UserRegistrationState {
    page: number;
    pageSize: number;
    sortColumn: SortColumnUserRegistrationInfo;
    sortDirection: SortDirectionUserRegistrationInfo;
}

const compare = (v1: string | number | boolean, v2: string | number | boolean) => v1 < v2 ? -1 : v1 > v2 ? 1 : 0;

function sort(userLists: UserRegistrationInfo[], column: SortColumnUserRegistrationInfo, direction: string): UserRegistrationInfo[] {
    if (direction === '' || column === '') {
        return userLists;
    }
    else {
        return [...userLists].sort((a, b) => {
            const res = compare(a[column], b[column]);
            return direction === 'asc' ? res : -res;
        });
    }
}

@Injectable({
    providedIn: 'root'
})
export class UserRegistrationService {
    private apiPATH = 'account/';
    public _search$ = new Subject<void>();
    private _userInfoLists$ = new BehaviorSubject<UserRegistrationInfo[]>([]);
    private _total$ = new BehaviorSubject<number>(0);

    private _state: UserRegistrationState = {
        page: 1,
        pageSize: 5,
        sortColumn: '',
        sortDirection: ''
    };

    constructor(private service: ApplicationService) {
        this._search$.pipe(
            debounceTime(200),
            switchMap(() => this._search()),
            delay(2000)).subscribe(result => {
                this._userInfoLists$.next(result.userLists);
                this._total$.next(result.total);
            });

        this._search$.next();
    }

    // getter functions
    get userInfoLists$() { return this._userInfoLists$.asObservable(); }
    get total$() { return this._total$.asObservable(); }
    get page() { return this._state.page; }
    get pageSize() { return this._state.pageSize; }

    // setter functions
    set page(page: number) { this._set({ page }); }
    set pageSize(pageSize: number) { this._set({ pageSize }); }

    set sortColumn(sortColumn: SortColumnUserRegistrationInfo) { this._set({ sortColumn }); }
    set sortDirection(sortDirection: SortDirectionUserRegistrationInfo) { this._set({ sortDirection }); }

    private _set(patch: Partial<UserRegistrationState>) {
        Object.assign(this._state, patch);
        this._search$.next();
    }

    private _search(): Observable<SearchResultUserRegistrationInfo> {
        const { sortColumn, sortDirection, pageSize, page } = this._state;

        // server call
        let allMemberLists: UserRegistrationInfo[] = [];        
        this.service.get<AccountListResultInfo>(`${this.apiPATH}lists`).subscribe(data => {
            if (data) {
                allMemberLists = data.Accounts;
                console.log("========== From Service ==============");
                console.log(allMemberLists);
            }
        });

        // 1. sort
        let userLists = sort(allMemberLists, sortColumn, sortDirection);

        const total = userLists.length;

        // 3. paginate
        userLists = userLists.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);

        return of({ userLists, total });
    }   
}

在此服务中,下面一行可以打印数据。

console.log("========== From Service ==============");
console.log(allMemberLists);

分量:

export class UserRegistrationListComponent implements OnInit {
userInfoLists$: Observable<UserRegistrationInfo[]>;
total$: Observable<number>;

@ViewChildren(UserRegistrationInfoSortableHeader) headers: 
QueryList<UserRegistrationInfoSortableHeader>;

constructor(
    public service: UserRegistrationService) {
}

ngOnInit(): void {      
    this.userInfoLists$ = this.service.userInfoLists$;
    this.total$ = this.service.total$;
        
     console.log("---------- In component1 -----------------");
     console.log(this.userInfoLists$);

    this.service.userInfoLists$.subscribe(data =>{
        console.log("---------- In component2 -----------------");
        console.log(data);
    })      
}

}

下面的代码在 ngOnInit 方法中不打印数据。所以我的 Table 没有获取数据。

this.userInfoLists$ = this.service.userInfoLists$;
this.total$ = this.service.total$;
            
console.log("---------- In component1 -----------------");
console.log(this.userInfoLists$);
    
this.service.userInfoLists$.subscribe(data =>{
   console.log("---------- In component2 -----------------");
   console.log(data);
})  

请帮我找到问题并解决。这是控制台输出:

问题在于您如何构建 _search() 函数以及您在可观察管道中设置的延迟 (2000)。


在_search函数中,return of()在API get订阅之外。这意味着 return 首先触发 然后 API get 订阅中的代码正在执行。 allMemberLists 被初始化为 [ ],所以 return 首先用 [ ] 发射。 但是,由于以下时间线,您看到的是 console.logs 的预期顺序。

  1. return 在 _search() 中用 [ ] 触发。 API 中的代码获取订阅尚未触发。
  2. 流水线的 switchmap 捕获 ([ ]) 的结果。但是 delay(2000) 阻止了订阅的代码,即 this._userInfoLists$.next([ ]) 尚未执行。
  3. API 中的代码现在触发获取订阅,您将获得 ==From 服务== console.log 和数据。
  4. 现在已经过去了 2000 毫秒。现在 this._userInfoLists$.next([ ]) 被触发了。
  5. 终于看到component2 console.log了。但是随着 [ ].

解决方案是避免为 API 调用设置这样的计时器。并避免订阅 API get in _search。而是在 _search() 中使用管道和映射运算符。您可以在 rxJS 官方文档中阅读 map() 的工作原理。

private _search(): Observable < SearchResultUserRegistrationInfo > {


    // ALL THE CODE GOES INSIDE THE server call     
    return this.service.get < AccountListResultInfo > (`${this.apiPATH}lists`).pipe(map(data => {
        const {
            sortColumn,
            sortDirection,
            pageSize,
            page
        } = this._state;
        let allMemberLists: UserRegistrationInfo[] = [];
        if (data) {
            allMemberLists = data.Accounts;
            console.log("========== From Service ==============");
            console.log(allMemberLists);
            let userLists = sort(allMemberLists, sortColumn, sortDirection);
            const total = userLists.length;
            userLists = userLists.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);
            // map() operator will automatically convert the returned value into an observable for me
            return {
                userLists,
                total
            };
        } else {
            // In case data is null
            return null
        }
    }));
}

让我知道它是否有效!