พฤติกรรมหัวเรื่อง RxJs เชิงมุม2

ฉันไม่ได้รับค่าการตอบสนองในองค์ประกอบที่มี BehaviorSubject ได้รับแล้วส่งต่อบริการครับ.

ฉันกำลังเรียกใช้ HTTP จากบริการบนตัวป้องกันเส้นทาง

บริการ:

@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();
            }
        );
    });
}

ส่วนประกอบ:

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>

มันเพิ่งได้รับพารามิเตอร์การสืบค้นสำหรับพารามิเตอร์ HTTP... guard:

@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)
   }
}

ฉันลองใช้ NgZone ด้วย แต่ฉันไม่แน่ใจว่ามันเป็นวิธีที่ถูกต้องหรือไม่:

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));
}

ป้อนคำอธิบายรูปภาพที่นี่


person Matej Maloča    schedule 19.12.2016    source แหล่งที่มา
comment
คุณมีปัญหาอะไร? คุณสามารถพูดถึงว่าคุณได้รับข้อผิดพลาดอะไร   -  person Avnesh Shakya    schedule 19.12.2016
comment
load() เรียกว่าที่ไหน? เหตุใดคุณจึงใช้สิ่งที่สังเกตได้ซ้อนกันจำนวนมาก   -  person Meir    schedule 19.12.2016
comment
ฉันไม่ได้รับข้อผิดพลาด... เพียงแค่ไม่แสดงผลข้อมูลใดๆ... ไม่สามารถรับการตอบสนอง HTTP ในส่วนประกอบได้ load() ถูกเรียกอย่างถูกต้องบนตัวป้องกันเส้นทาง (canActivate)   -  person Matej Maloča    schedule 19.12.2016


คำตอบ (1)


ก่อนอื่น: อย่าสมัครสมาชิกสิ่งที่สังเกตได้อื่นภายในสิ่งที่สังเกตได้ ให้เขียนเป็นสตรีมแทน:

@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));
}

และประการที่สอง: อย่าสมัครรับข้อมูลสตรีมที่ไม่มีที่สิ้นสุดด้วยตนเองเพื่อเขียนผลลัพธ์ไปยังสมาชิกของคลาส ให้ใช้ async-pipe แทน:

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

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

แม่แบบ:

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

หากปัญหาการโหลดของคุณยังคงอยู่ คุณอาจต้องการแบ่งปันเนื้อหาของเมธอด api.send (เว้นแต่จะมีการเรียกอย่างแน่นอน)

ความเป็นไปได้ประการหนึ่งคือต้องใช้วิธีอะซิงก์ที่ทำงานนอก ngZone จากนั้นคุณอาจต้องการลองทำสิ่งต่อไปนี้:

  • ฉีด NgZone (จาก "@เชิงมุม/แกน") ในบริการของคุณ
  • ล้อมการดำเนินการภายใน this._api.send- โทรภายใน ngZone.run
  • ดูที่นี่สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ NgZone: https://angular.io/docs/ts/latest/api/core/index/NgZone-class.html
person olsn    schedule 19.12.2016
comment
ก่อนอื่นฉันขอขอบคุณความพยายามของคุณขอบคุณ ฉันลองทุกสิ่งที่คุณเขียน คุณพูดถูกต้องในสิ่งที่สังเกตได้ภายในสิ่งที่สังเกตได้ ฉันไม่ได้ระบุโค้ดส่วนประกอบทั้งหมดที่ฉันยกเลิกการสมัครที่ ngOnDestroy API นั้นสะอาดและเมื่อฉัน console.log(temp) ให้บริการ ฉันได้รับข้อมูลที่ฉันต้องการ แต่ไม่ได้อยู่ในองค์ประกอบที่ฉันได้รับอาร์เรย์ว่าง ฉันไม่มีข้อผิดพลาดในคอนโซล ดังนั้นฉันจึงไม่รู้ว่าต้องทำอย่างไร คำแนะนำใด ๆ จะช่วยฉันได้ ฉันไม่รู้ว่ามันไม่เกี่ยวข้อง แต่ฉันอัปเดตแอพนี้อย่างทะเยอทะยานจาก rc6 เป็น 4.0.0-beta.0 และทุกอย่างทำงานได้ดียกเว้น BehaviorSubject นี้ - person Matej Maloča; 20.12.2016
comment
และฉันก็ลอง NgZone ด้วยแต่ไม่แน่ใจว่ามันเป็นวิธีที่ถูกต้องหรือไม่... ตรวจสอบการแก้ไขโพสต์หลัก... - person Matej Maloča; 20.12.2016
comment
คุณเพียงแค่ต้องล้อมการโทร .next ใน ngZone.run - ซึ่งควรทำไปแล้ว ไม่จำเป็นต้องมีการเรียกกลับหลายชั้น ฯลฯ :) - person olsn; 21.12.2016
comment
ถึงกระนั้นก็ไม่ได้ผล ฉัน console.log(projects$) บนปุ่มคลิกแบบสุ่ม ดังนั้นฉันจึงเตรียมภาพหน้าจอไว้ - person Matej Maloča; 21.12.2016
comment
ฉันทำให้มันทำงานได้สำเร็จ แต่ฉันต้องลดระดับแพ็คเกจจำนวนมากรวมถึงเชิงมุมเป็น 2.1 ... ยังคงไม่เข้าใจว่าอันไหนที่ทำลายมันโดยไม่มีข้อผิดพลาด .... - person Matej Maloča; 21.12.2016