【问题标题】:Wait for Service Api call to complete in Angular 8等待服务 API 调用在 Angular 8 中完成
【发布时间】:2020-08-04 20:39:46
【问题描述】:

我正在尝试我的第一个 Angular 8 Crud Web 应用程序并编写了一个页面来列出来自 WebApi 的一些公司名称

我的服务正在正确获取数据并且我能够在控制台上打印它

//Service.ts
export class CompanyService {
  allCompanys: Company[]
  constructor(private httpClient: HttpClient) { }
  // Returns all the companys
  GetAll(): Company[] {

    this.httpClient.get<Company[]>('https://localhost:565656/api/company').subscribe(result => {
      this.allCompanys = result;

      //Shows data Sucessfully from Server :Working fine
      console.log(this.allCompanys);

    }, error => console.error(error));

    return this.allCompanys;
  }

但是在我的组件中,我尝试通过调用服务来获取页面开头的数据并将其分配给本地变量,它给出了未定义的

     ///Component.ts

      export class CompanyListComponent implements OnInit {
      Companylist: Company[] 
 constructor(private route: ActivatedRoute, private router: Router, private companyService: CompanyService) {  }
        ngOnInit() {

          this.Companylist = this.companyService.GetAll();  
          //This is executing before the service call is returning and returning Undefined
          console.log("At Component " + this.Companylist)

        }

我的 html 如下所示,表格未显示

  //html

      <tr *ngFor="let company of Companylist">
      <td>{{company.Name}}</td>
      <td>{{company.Phone}}</td>
      <td>{{company.Email}}</td>
      <td>{{company.Address}}</td>
       < /tr>

我也尝试了 Observables 但没有工作。我需要在调用 api 后绑定变量。有人可以建议我做错了什么

我已经检查过SO中的类似案例,但找不到类似的东西(我可能不理解)

【问题讨论】:

  • 当你这样分配变量时,它不会等待异步请求结束,你的 GetAll() 方法应该返回一个可观察的并在你的组件中订阅它,然后分配你的局部变量当 observable 完成时

标签: angular rxjs angular8


【解决方案1】:

http 请求是作为异步操作完成的,因此将开始请求,但 getAll 异步执行,因此将立即到达 return 语句并返回每个 allCompanys 所拥有的内容。

要解决这个问题,您需要更新 GetAll 以返回一个 observable

GetAll(): Observable<Company[]> {
   return  this.httpClient.get<Company[]>('https://localhost:565656/api/company')
}

在你订阅getAll的组件处

this.companyService.GetAll().subscribe( result=> this.Companylist = result ); 

我们可以用async管道

简化上面的代码
Companylist$ : Observable<Company[]>;

ngOnInit(){

Companylist$ = this.companyService.GetAll();

}

模板

<tr *ngFor="let company of Companylist$ | async">
...
</tr>

异步管道订阅 observable 并返回它发出的最新值。

? 另一种方法是使用async/await,因此我们需要更新GetAll 以返回一个promise,并且使用toPromise 方法很容易将observable 转换为promise

GetAll(): Promise<Company[]> {
   return  this.httpClient.get<Company[]>('https://localhost:565656/api/company')
          .toPromise(); // ?
}

组件

async ngOnInit() {

  this.Companylist = await this.companyService.GetAll();  
   ...
}

在这里阅读更多信息?async/await

【讨论】:

    【解决方案2】:

    问题是因为您在异步调用 this.httpClient.get&lt;Company[]&gt;('https://localhost:565656/api/company') 得到解决之前返回了 this.allCompanys

    您可以像 return this.httpClient.get('https://localhost:565656/api/company') 一样返回 Observable Company[] 并像 allCompanys | async 这样在您的视图中捕获它 或者您可以从您的方法中删除该返回 Company[] 类型并将其替换为 void,删除返回并让 this.allCompanys = result 就像它在订阅中一样,这样您也可以控制它的值(当它被解析时),例如 @987654326 @

    【讨论】:

      【解决方案3】:

      最容易理解的代码

      在你的组件中:

      ngOnInit() {
          // callback gets executed when your service gets the response in the API call
          const callback = function(companyList: Company[]) {
            this.Companylist = companyList;
          }
          this.companyService.GetAll(callback);
          console.log("At Component " + this.Companylist)
      }
      

      在您的服务中:

      GetAll(callback?: Function) {
      
          this.httpClient.get<Company[]>('https://localhost:565656/api/company').subscribe(result => {
            this.allCompanys = result;
      
            //Shows data Sucessfully from Server :Working fine
            console.log(this.allCompanys);
            if(callback) {
              callback(this.allCompanys);
            }
      
          }, error => console.error(error));
      }
      

      【讨论】:

        【解决方案4】:

        在服务中,this.allCompanys 甚至在您得到响应之前就已同步返回。所以它返回Undefined。但是当响应到来时,组件不再检查更新。

        所以你需要异步更新值。

        GetAll(): Company[] {
            return this.httpClient.get<Company[]>('https://localhost:565656/api/company');
        }
        

        在组件中

        this.companyService.GetAll().subScribe((res) => {
            this.Companylist = res;
        }, error => console.error(error)
        )
        

        【讨论】:

          猜你喜欢
          • 2018-04-20
          • 1970-01-01
          • 1970-01-01
          • 2019-03-08
          • 2019-03-25
          • 2018-12-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多