【问题标题】:Angular 9: Subscribe call causes page refreshAngular 9:订阅调用导致页面刷新
【发布时间】:2020-05-02 09:20:09
【问题描述】:

我正在尝试在 Angular 9 中制作一个向 Google Books API 发出请求的应用程序。

但是,requestBookByISBN(isbn: string) 中的 .subscribe 调用会导致页面刷新。我想避免这种情况。

  private callAPI(isbn: string): Observable<GoogleBook[]> {

    return this.httpClient
        .get<{ results: GoogleBook[] }>
        (`https://www.googleapis.com/books/v1/volumes?q=${isbn}&key=${ApiLookupService.API_KEY}`)
        .pipe(map(matches => matches.results || []));
  }

  public requestBookByIsbn(isbn: string): GoogleBook[] {
    const bookResults: Observable<GoogleBook[]> = this.callAPI(isbn);
    let books: GoogleBook[] = [];
    bookResults.subscribe(data => books = data);
    return books;
  }

编辑:这是 component.ts 文件的一部分,其中包含代码的相关部分:

import {Component, OnInit} from '@angular/core';
import {BookServiceImpl} from '../../shared/Book/service/book.service.impl';
import {CopyServiceImpl} from '../../shared/Copy/service/copy.service.impl';
import {AuthorServiceImpl} from '../../shared/Author/service/author.service.impl';
import {FormControlSettings} from '../FormControlSettings/form.controls.settings';
import {FormBuilder, FormControl, FormGroup} from '@angular/forms';
import {Author} from '../../shared/Author/model/Author';
import {first} from 'rxjs/operators';
import {ToastrService} from 'ngx-toastr';
import {Book} from '../../shared/Book/model/Book';
import {Copy} from '../../shared/Copy/model/Copy';
import {SharedService} from '../../shared/services/shared.service';
import {Subscription} from 'rxjs';
import {ApiLookupService} from '../../shared/services/api.lookup.service';

@Component({
    selector: 'app-addbook',
    templateUrl: './addbook.component.html',
    styleUrls: ['./addbook.component.css']
})
export class AddbookComponent implements OnInit {
    // forms 
    public submitted = false;
    public loading = false;
    public error = '';
    public initAuthorsSubscription: Subscription;
    public authors: Author[] = [];
    public selectedAuthors: Author[]; // chosen in ng select

    constructor(private bookService: BookServiceImpl,
                private copyService: CopyServiceImpl,
                private authorService: AuthorServiceImpl,
                private formBuilder: FormBuilder,
                private toastr: ToastrService,
                public sharedService: SharedService,
                public apiLookupService: ApiLookupService) {
    }

    public ngOnInit(): void {
        this.initAuthors();
        this.initBookForm();
        this.getInitAuthorsEvent();
    }

    public findAuthors(ids: number[]): Author[] {
        const authors = [];
        for (const id of ids) {
            this.authorService.findById(id).subscribe(value => authors.push(value));
        }
        console.log(authors);
        return authors;
    }

    public isbnLookUp() {
        console.log(this.apiLookupService.requestBookByIsbn(this.isbnControl.value));
    }

    public initBookForm(): void {
        // assinging form controls

        this.bookForm = new FormGroup({
        // more assigning going on here 
        });
    }

    public initAuthors() {
        this.authorService.findAll().subscribe(data => {
            this.authors = data.map((author) => {
                author.fullName = this.authorService.getFullName(author);
                return author;
            });
        });
    }

    public getInitAuthorsEvent(): any {
        this.initAuthorsSubscription = this.sharedService.initAuthors().subscribe(
            () => this.initAuthors());
    }

    public onSubmit() {
        // values are assigned here 

        this.bookService.add(book)
            .pipe(first())
            .subscribe(
                data => {
                    this.toastr.success('Buch erfolgreich hinzugefügt!');
                    copy.reference = data;
                    for (let i = 0; i < this.amountControl.value; i++) {
                        this.copyService.add(copy).pipe(first()).subscribe();
                    }
                    /*this.sharedService.sendCloseModal();
                    this.sharedService.sendCloseModal();*/
                },
                error => {
                    this.loading = false;
                    this.toastr.warning(error);
                    this.error = error;
                }
            );
    }
}

另一个猜测是与其他订阅调用存在冲突。

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    我不确定这是否是它刷新的原因,但bookResults.subscribe 是一个异步操作,因此您实际上是在返回一个空数组,然后在某个未指定的点将其修改为完整数据。

    您有两种选择来解决该特定问题:使用 RXjs 或 Promise:

    RXjs 选项:

      public requestBookByIsbn(isbn: string): GoogleBook[] {
        return this.callApi(isbn);
      }
    

    然后让调用requestBookByIsbn的组件订阅并在该点设置组件中的数据。

    承诺选项:

      public async requestBookByIsbn(isbn: string): GoogleBook[] {
        const bookResults: Promise<GoogleBook[]> = this.callAPI(isbn).toPromise();
        return await bookResult;
      }
    

    我猜刷新发生的位置可能超出了您向我们展示的部分。

    如果您要重定向到“/login”以检查用户是否已登录,那么在该重定向中,您应该将当前路径添加为history state 或查询参数,然后在登录后重定向到该路径完成而不是重定向到 '/'。

    【讨论】:

    • 我尝试将 requestBookByIsbn 放入 ngOnInit() 只是为了看看是什么原因造成的。出于某种原因,即使我没有导入路由器,它也会重新路由到 /login。
    • 您是否有路由守卫来确保您已登录?
    • 我使用 JWT 和本地存储来确保我已登录。我应该更清楚:它将我重新路由到 /login,将我重定向到 /
    • 听起来您的问题绝对是路由器而不是书籍结果。除非您的 ApiLookupService.API_KEY 是由于 getter 而导致问题,并且它必须检查您是否已登录。
    • 看起来问题也不在于路由器,它在其他地方都可以正常工作 - 我猜这是方法 callAPI 的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 2018-11-27
    • 2019-03-14
    • 2019-01-10
    • 2019-02-08
    • 1970-01-01
    • 2016-04-30
    相关资源
    最近更新 更多