【问题标题】:How do you handle the order of functions in Angular?你如何处理 Angular 中的函数顺序?
【发布时间】:2020-11-07 21:03:46
【问题描述】:

所以我有一个 Angular 组件。

对于一些包含我想要使用的数据的数组对象:

  books: Book[] = [];
  reviews: Review[] = [];

这就是我的 ngOnInit() 的样子:

  ngOnInit(): void {
    this.retrieveBooks();
    this.retrieveReviews();
    this.setRatingToTen();
  }

我用这个写书和评论到对象数组。 这是通过服务“订阅”数据来完成的:

  retrieveBooks(): void {
    this.bookService.getAll()
      .subscribe(
        data => {
          this.books = data;
        },
        error => {
          console.log(error);
        }
      );
  }

  retrieveReviews(): void {
    this.reviewService.getAll()
      .subscribe(
        data => {
          this.reviews = data;
        },
        error => {
          console.log(error);
        });
  }

所以我的下一个函数只是“处理数据”的一个例子。

在此示例中,我只想将每本书的所有总评分更改为 10:

  setRatingToTen(): void {
    this.books.forEach(element => {
      element.totalrating = 10;
    });
    console.log(this.books);
  }

我一直试图解决的问题是:

this.books 是一个空数组

我认为原因是因为这个函数在数据订阅之前运行。

如果是这样,那我对ngOnInit的理解肯定不对。

我以为它会按顺序调用函数。

也许还是这样,只是它们没有按顺序完成。

所以我的问题是:

1.为什么是空数组?

(我说的对吗?还是还有更多?)

2。 Angular 开发人员如何编写函数以使它们以所需的顺序运行?

(因为数据需要在那里以便我可以使用它,我该如何避免这个问题?)

(3.) 额外问题:

(如果你有时间,请,谢谢)

我的目标是为每本 this.reviews.title 等于 this.books.title 的书拉 this.reviews.rating,得到一个平均分;然后用平均值覆盖 this.books.totalrating 的“0”占位符。我怎样才能重写 setRatingToTen() 函数来完成这个?

【问题讨论】:

    标签: javascript angular typescript mean


    【解决方案1】:

    这是在 rxjs 中使用 forkJoin 方法的解决方案之一。

    您可以查看此以获取详细信息https://medium.com/@swarnakishore/performing-multiple-http-requests-in-angular-4-5-with-forkjoin-74f3ac166d61

    工作演示:enter link description here

    ngOnInit:

    ngOnInit(){
        this.requestDataFromMultipleSources().subscribe(resList => {
            this.books = resList[0];
            this.reviews = resList[1];
            this.setRatingToTen(this.books,this.reviews);
        })
    }
    

    forkJoin 方法:

    public requestDataFromMultipleSources(): Observable<any[]> {
        let response1 = this.retrieveBooks();
        let response2 = this.retrieveReviews();
        // Observable.forkJoin (RxJS 5) changes to just forkJoin() in RxJS 6
        return forkJoin([response1, response2]);
      }
    

    其他方法:

    retrieveBooks(): void {
        this.bookService.getAll()
          .subscribe(
            data => {
              this.books = data;
            },
            error => {
              console.log(error);
            }
          );
      }
    
      retrieveReviews(): void {
        this.reviewService.getAll()
          .subscribe(
            data => {
              this.reviews = data;
            },
            error => {
              console.log(error);
            });
      }
      
      setRatingToTen(books, reviews): void {
        this.books.forEach(element => {
          element.totalrating = 10;
        });
        console.log(this.books);
      }
    

    【讨论】:

    • this.requestDataFromMultipleSources().subscribe(resList => { 在这一行我收到错误消息:您在预期流的位置提供了“未定义”。您可以提供 Observable、Promise、Array、或可迭代。
    • 我希望你不会错过 import forkJoin import { forkJoin } from 'rxjs';
    • 不,它就在那里。我唯一改变的是 this.setRatingToTen(this.games, this.reviews),因为逗号是句号,我认为这是一个明显的错字。
    • 您能帮我分享一下工作代码 ion codesandbox 或 stackblitz 吗?
    • 好的,看看它为什么我的不起作用。这可能与我的服务返回 Review[] 和 Book[] 对象而不是 json 有关吗?
    【解决方案2】:

    Angular 大量使用 observables 来处理各种 异步 操作。发出服务器端请求(通过 HTTP)就是其中之一。

    您的前两个问题清楚地表明您忽略了可观察对象的异步性质

    Observable 是 惰性 推送集合多个值detailed link

    意味着可观察到的响应将以异步方式随时间推送。您无法保证这两个不同的函数中的哪一个会首先返回其响应。

    话虽如此,rxjs 库(Observables 也是这个库的一部分,并且 Angular 从这里借用了它们)提供了丰富的 operators 集合,您可以使用它们来操纵 observables。

    有了上面的解释,这里就为你的问题一一解答。

    1.为什么是空数组?

    因为您正在考虑代码的同步顺序流,其中一个方法只有在另一个方法完成工作后才会被调用。但是这里 retrieveBooksretrieveReviews 都在进行 异步(可观察)调用,然后订阅它。这意味着无法保证何时会收到他们的回复。同时,已经对 setRatingToTen 进行了命中,此时 books 数组为空。

    2。 Angular 开发人员如何编写函数以使它们以所需的顺序运行?

    Angular 开发人员会理解 异步可观察 调用的性质,并且会按顺序管道操作符,以便他们在执行任何操作之前确定他们手头有响应对可观察流的进一步操作。

    (3.) 额外问题:

    您的要求规定,在执行任何操作之前,您必须首先获得两个可观察对象的响应。对于那个 forkJoin rxjs 运算符适合您的需要。该运算符的文档说

    一个常见的用例是,如果您希望在页面加载(或某些其他事件)时发出多个请求,并且只想在收到所有响应时采取行动。 detailed link

    不确定您的平均得分策略,但这里有一个示例代码,您将如何实现您的目标。

    ngOnInit(){
    let req1$ = this.bookService.getAll();
    let req2$ = this.reviewService.getAll();
    forkJoin(req1$, req2$).subscribe(([response1, response2])=>{
    for(let book of response1) //loop through book array first
    {
     for(let review of response2) //inner loop of reviews
    {
    if(book.title == review.title)
    {
    //complete your logic here..
    }
    }
    
    }
      });
    
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-14
      • 2018-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多