有没有办法告诉 Firestore 获取并等待,以便 Angular SSR 将在服务器而不是客户端中呈现响应数据?

问题描述 投票:0回答:1

我的目标是从 Firestore 获取数据并在服务器中渲染响应数据。

问题是,Firestore 以某种方式设法告诉组件不要等待,而只是将 HTML 发送到客户端。

如果我在 ngOnInit 中添加

setTimeout(() => {}, 1000)
,响应数据将在服务器中渲染。但是,显然,这是一种黑客行为,并且不能保证。

我正在使用 Angular 17。

@Component({
  selector: 'app-experience',
  standalone: true,
  imports: [
    NgIf,
    AsyncPipe,
    RouterLink,
  ],
  templateUrl: './experience.page.html',
  styleUrl: './experience.page.scss'
})
export class ExperiencePage implements OnInit {
  documentId: Signal<string | null>;
  
  slug: Signal<string | null>;

  experience: Promise<Experience | null> = Promise.resolve(null);

  constructor(
    route: ActivatedRoute,
    getExperience: GetExperienceUseCaseService,
    private firestore: Firestore,
  ) {
    const queryParamMap = route.queryParamMap;

    // RxJs Interop
    // see https://angular.io/guide/rxjs-interop
    this.slug = toSignal(
      queryParamMap.pipe(map((params) => params.get("slug"))),
      { initialValue: null }
    );
    
    this.documentId = toSignal(
      queryParamMap.pipe(map((params) => params.get("documentId"))),
      { initialValue: null }
    );

    const collectionReference = collection(this.firestore, 'experiences');
    const documentReference = doc(collectionReference, "CKfKFpCimmBxZpUJktud");
    const documentSnapshot = getDoc(documentReference);

    documentSnapshot.then((snapshot) => {
      if (!snapshot.exists()) { return; }

      const data = snapshot.data();

      this.experience = Promise.resolve({
        title: data["experienceTitle"],
        type: data["experienceType"],
        category: data["experienceCategory"],
        rating: data["rating"],
      });
    })
  }

  ngOnInit() {
    setTimeout(() => {
      console.log("wait");
    }, 1000)
  }
}
angular angular-universal angular-ssr
1个回答
0
投票

尝试将代码移至ngOnInit,为什么它在

constructor
上?也许 SSR 等待
ngOnInit
完成而不是
constructor

@Component({
  selector: 'app-experience',
  standalone: true,
  imports: [NgIf, AsyncPipe, RouterLink],
  templateUrl: './experience.page.html',
  styleUrl: './experience.page.scss',
})
export class ExperiencePage implements OnInit {
  documentId: Signal<string | null>;

  slug: Signal<string | null>;

  experience: Promise<Experience | null> = Promise.resolve(null);

  constructor(
    route: ActivatedRoute,
    getExperience: GetExperienceUseCaseService,
    private firestore: Firestore
  ) {}

  ngOnInit() {
    const queryParamMap = this.route.queryParamMap;

    // RxJs Interop
    // see https://angular.io/guide/rxjs-interop
    this.slug = toSignal(
      queryParamMap.pipe(map((params) => params.get('slug'))),
      { initialValue: null }
    );

    this.documentId = toSignal(
      queryParamMap.pipe(map((params) => params.get('documentId'))),
      { initialValue: null }
    );

    const collectionReference = collection(this.firestore, 'experiences');
    const documentReference = doc(collectionReference, 'CKfKFpCimmBxZpUJktud');
    const documentSnapshot = getDoc(documentReference);

    documentSnapshot.then((snapshot) => {
      if (!snapshot.exists()) {
        return;
      }

      const data = snapshot.data();

      this.experience = Promise.resolve({
        title: data['experienceTitle'],
        type: data['experienceType'],
        category: data['experienceCategory'],
        rating: data['rating'],
      });
    });
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.