angular - Angular 订阅从 API 返回的数据
问题描述
我正在尝试清理我的 Ionic 应用程序并将冗余功能移动到提供程序中。下面是我的大多数 API 函数的示例(为了简洁起见,我删除了很多不相关的东西)并且它们运行良好。
getDataFromApi() {
....
Promise.all([
...
]).then((result) => {
let headers = new Headers();
...
let body = new FormData();
...
this.http.post(url, body, headers)
.map(res => res.json())
.subscribe(data => {
if (data == '{}') {
this.mydata = [];
} else {
this.mydata = data;
}
}, error => { });
});
}
所以我所做的就是将函数移动到提供程序中并像这样改变它
getDataFromApi() {
....
Promise.all([
...
]).then((result) => {
let headers = new Headers();
...
let body = new FormData();
...
return this.http.post(url, body, headers));
});
}
然后在页面的构造函数中我这样称呼它
this.service.getDataFromApi()
.map(res => res.json())
.subscribe(data => {
if (data == '{}') {
this.mydata = [];
} else {
this.mydata = data;
}
}, error => { });
显然这是行不通的。我已经倾注了 2 天的 SO 帖子,也无法让其他人的示例和答案正常工作。我已经尝试在提供程序中进行映射并在页面中调用它时进行订阅,但无论我尝试什么,都会不断收到错误。我知道这个函数正在返回数据,因为我可以在将它移动到提供程序之前看到它。
我究竟做错了什么?
解决方案
我认为最重要的是保持一致;你可以只使用Promise 或只使用 observables来完成所有这些工作(而不是混合使用两者)。
请看一下这个 stackblitz 演示,在那里你可以看到如何只使用 observables 来发出类似的 HTTP 请求,以及只使用 Promise 来发出完全相同的请求。
使用可观察对象
您可以使用switchMap
(或任何其他展平运算符)与fromPromise
提供者以相同的方法处理所有这些:
// Angular
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
// RxJS
// Please notice that this demo uses the 5.5.2 version
import { Observable } from 'rxjs/Observable';
import { map } from 'rxjs/operators/map';
import { tap } from 'rxjs/operators/tap';
import { switchMap } from 'rxjs/operators/switchMap';
// ...
// Get a list of 5 users using observables
public getDataUsingObservables(): Observable<any> {
const promises = Promise.all([
this.somePromise('getDataUsingObservables', 1),
this.somePromise('getDataUsingObservables', 2)
]);
return fromPromise(promises)
.pipe(
switchMap(results => {
console.log(`[getDataUsingObservables]: Both promises are finished`);
const url = `https://randomuser.me/api/?results=5`;
return this.http.get<any>(url);
}),
tap(res => {
console.log(`[getDataUsingObservables]: The http request is finished`);
})
);
}
// Return a promise with the number sent as parameter
private somePromise(callerMethod: string, aNumber: number): Promise<number> {
console.log(`[${callerMethod}]: About to create a promise with the number ${aNumber}`);
return Promise.resolve(aNumber);
}
然后你会像这样使用它:
this.dataService.getDataUsingObservables().subscribe(
response => {
this.responseUsingObservables = response;
},
error => {
// Handle the error...
alert(error);
});
使用承诺
如果要使用 Promise,可以使用toPromise()
操作符将 observable 转换为 Promise:
// Angular
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
// RxJS
// Please notice that this demo uses the 5.5.2 version
import { tap } from 'rxjs/operators/tap';
// ...
// Get a list of 5 users using promises
public getDataUsingPromises(): Promise<any> {
const promises = Promise.all([
this.somePromise('getDataUsingPromises', 1),
this.somePromise('getDataUsingPromises', 2)
]);
return promises
.then(results => {
console.log(`[getDataUsingPromises]: Both promises are finished`);
const url = `https://randomuser.me/api/?results=5`;
return this.http.get<any>(url)
.pipe(
tap(res => {
console.log(`[getDataUsingPromises]: The http request is finished`);
})
)
.toPromise();
});
}
// Return a promise with the number sent as parameter
private somePromise(callerMethod: string, aNumber: number): Promise<number> {
console.log(`[${callerMethod}]: About to create a promise with the number ${aNumber}`);
return Promise.resolve(aNumber);
}
然后你会像这样使用它:
this.dataService.getDataUsingPromises()
.then(response => {
this.responseUsingPromises = response;
})
.catch(error => {
// Handle the error...
alert(error);
});
推荐阅读
- typescript - Github Action- 拉取请求中的一些 EsLint 错误不会显示 Annonations
- java - 使用 Stream 遍历路径时实现自定义逻辑
- docker-compose - BitBucket Pipelines 中的 Docker Compose
- php - 在 MacOS 上运行 PHP v5.4
- java - PGP_Sym_Encrypt 在休眠中不起作用,但在使用手动插入查询时起作用
- c# - 用户作为 ASP Net Core 中的范围服务 - 不好的做法?
- pygame - 如何在 pyopengl 中使用鼠标单击来移动立方体?
- security - Trivy 和 Dependency-Check 报告不同的漏洞
- windows - 我已经尝试了几乎所有可以从网上找到的东西。没有。有没有办法合并一个字符串和一个变量,批量打开一个程序?
- elasticsearch - NEST 7X ElasticSearch 库的多用户连接