PerilakuSubjek RxJs sudut2

Saya tidak mendapatkan nilai respon dalam komponen dengan BehaviorSubject. Saya mendapatkannya dan meneruskannya ke layanan.

Saya memicu HTTP dari layanan di penjaga rute.

melayani:

@Injectable()
export class ProjectsService {
projects: Subject<Project[]> = new BehaviorSubject<Project[]>([]);

load(clientId: string, active: boolean): Observable<boolean> {
    return new Observable<boolean>((obs) => {
        this._api.send(active ? 'projects.getActive' : 'projects.getAll',clientId).subscribe(
            res => {
                let temp = [];
                res.forEach(a => temp.push(new Project(a)));

                if (active) this.projects.next(temp);
                else this.externalProjects.next(temp);
                obs.next(true);
                obs.complete();
            },

            err => {
                obs.next(false);
                obs.complete();
            }
        );
    });
}

komponen:

ngOnInit(): void {
    // todo: check why not to load already added
    this._projectsListener = this._projectsService.projects.subscribe(a => {
        this.showIntro = a.length ? false : true;
        this.projects = a;
    });
 }

HTML:

<div class="project" [hidden]="!showIntro" *ngFor="let project of projects>
  {{project.title}}
</div>

Itu hanya mendapatkan parameter kueri untuk parameter HTTP... penjaga:

@Injectable()
export class ProjectsGuard implements CanActivate {
   constructor(
       private _projectsService: ProjectsService,
       private _router: Router) {}

   canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
       return this._projectsService.load(next.params['id'], true)
   }
}

Saya juga mencoba NgZone tetapi saya tidak yakin apakah ini cara yang benar:

load(clientId: string, active: boolean): Observable<boolean> {
    return this._api.send(active ? 'projects.getActive' : 'projects.getAll',clientId)
        .map(res => {
            let temp = res.map(a => new Project(a));

            this._ngZone.run(() => {
                console.log('temp: ', temp);
                if (active) this.projects.next(temp);
                else this.externalProjects.next(temp);
            });

            return true;
        })
        .catch(() => Observable.of(false));
}

masukkan deskripsi gambar di sini


person Matej Maloča    schedule 19.12.2016    source sumber
comment
Masalah apa yang Anda alami? Anda bisa menyebutkan, kesalahan apa yang Anda dapatkan.   -  person Avnesh Shakya    schedule 19.12.2016
comment
Di mana load() dipanggil? Mengapa Anda menggunakan begitu banyak observasi bersarang?   -  person Meir    schedule 19.12.2016
comment
Saya tidak mendapatkan kesalahan... hanya tidak merender data apa pun... tidak bisa mendapatkan respons HTTP dalam suatu komponen. load() dipanggil dengan benar pada penjaga rute (canActivate).   -  person Matej Maloča    schedule 19.12.2016


Jawaban (1)


Pertama-tama: Jangan berlangganan observasi lain di dalam observasi. Sebaliknya, tulislah sebagai aliran:

@Injectable()
export class ProjectsService {
projects: Subject<Project[]> = new BehaviorSubject<Project[]>([]);

load(clientId: string, active: boolean): Observable<boolean> {
    return this._api.send(active ? 'projects.getActive' : 'projects.getAll',clientId)
        .map(res => {
                let temp = res.map(a => new Project(a));

                if (active) {
                    this.projects.next(temp);
                } else {
                    this.externalProjects.next(temp);
                }
                return true;
            })
       .catch(() => Observable.of(false));
}

Dan kedua: Jangan berlangganan aliran tanpa akhir secara manual untuk menulis hasilnya ke anggota kelas, gunakan pipa async sebagai gantinya:

public projects$: Observable<Project[]> = this._projectsService.projects;
public showIntro$: Observable<boolean> = this.projects$
    .map(projects => projects.length > 0);

ngOnInit(): void {
    // ...nothing to do here
}

Templat:

<div class="project" [hidden]="!showIntro" *ngFor="let project of (projects$ | async)>
  {{project.title}}
</div>
....somewhere else:
<div *ngIf="showIntro$ | async">INTRO!</div>

Jika masalah pemuatan Anda masih berlanjut, Anda mungkin ingin membagikan konten metode api.send (kecuali jika hal tersebut disebutkan secara pasti).

Salah satu kemungkinannya adalah memiliki metode async yang berjalan di luar ngZone, maka Anda mungkin ingin mencoba yang berikut:

person olsn    schedule 19.12.2016
comment
Pertama-tama, saya menghargai usaha Anda, terima kasih. Saya mencoba semua hal yang Anda tulis. Anda benar tentang observasi di dalam observasi. Saya tidak memberikan semua kode komponen tempat saya berhenti berlangganan di ngOnDestroy. API-nya bersih dan ketika saya console.log(temp) dalam layanan saya mendapatkan data yang saya inginkan tetapi tidak dalam komponen tempat saya mendapatkan array kosong. Saya tidak mendapatkan kesalahan di konsol jadi saya tidak tahu apa yang harus dilakukan, saran apa pun akan membantu saya. Saya tidak tahu apakah ini tidak relevan tetapi saya secara ambisius memperbarui aplikasi ini dari rc6 ke 4.0.0-beta.0 dan semuanya berfungsi dengan baik kecuali BehaviorSubject ini. - person Matej Maloča; 20.12.2016
comment
Dan saya juga mencoba NgZone tetapi tidak yakin apakah itu cara yang benar... periksa edit postingan utama... - person Matej Maloča; 20.12.2016
comment
Anda hanya perlu menggabungkan panggilan .next dalam ngZone.run - itu seharusnya sudah berhasil, tidak perlu banyak lapisan panggilan balik, dll. :) - person olsn; 21.12.2016
comment
Tetap saja, tidak berhasil. Saya console.log(projects$) pada beberapa tombol klik acak, jadi saya berikan tangkapan layar. - person Matej Maloča; 21.12.2016
comment
Saya berhasil membuatnya berfungsi, tetapi saya perlu menurunkan banyak paket termasuk paket sudut ke 2.1... masih belum mengerti mana yang merusaknya tanpa kesalahan.... - person Matej Maloča; 21.12.2016