将多个嵌套的 Promise 和 Promise 数组转换为 Observables
Posted
技术标签:
【中文标题】将多个嵌套的 Promise 和 Promise 数组转换为 Observables【英文标题】:Converting multiple nested promises and array of promises to Observables 【发布时间】:2019-05-19 23:38:33 【问题描述】:我正在使用 TypeScript 将 AngularJS 应用程序转换为 Angular 7。
我在将一些复杂的嵌套 Promise 转换为 Observables 时遇到了一些问题。
这是我正在处理的代码示例:
signup.component.js
function SomethingSignupController(somethingApplication)
function activate()
getApplication();
function getApplication()
vm.getFromServer = false;
vm.promises = [];
SomethingRepo.get().then(function(application)
vm.getFromServer = true;
vm.application = application;
vm.promises.push(Something.getCompany().then(function(company)
vm.company = company;
if (vm.company.structure === ‘more_25’)
return SomethingRepo.getAllOwners().then(function(owners)
vm.owners = owners;
for(var i = 0; i < vm.owners.length; i++)
vm.promises.push(getOwnerFiles(vm.owners[i]));
vm.promises.push(SomethingRepo.getSomethingOne().then(function(somethingOne)
vm.somethingOne = somethingOne;
vm.promises.push(SomethingRepo.getSomethingTwo().then(function(somethingTwo)
vm.somethingTwo = somethingTwo;
vm.promises.push(SomethingRepo.getSomethingThree().then(function(somethingThree)
vm.somethingThree = somethingThree;
/* and a few more like the above */
$q.all(vm.promises).then(function()
postGet();
).finally(function()
vm.promises = [];
);
function postGet()
/* does something with the data acquired from SomethingRepo */
/* when an application is send */
function send()
somethingApplication.promises = [];
somethingApplication.errors = [];
if (vm.getFromServer)
update();
else
create();
function update()
somethingApplication.promises.push(SomethingRepo.update(vm.application).then(angular.noop, function(error)
somethingApplication.parseErrors(error, ‘Some error’);
));
patchInfo();
function create()
function patchInfo()
somethingApplication.promises.push(SomethingRepo.patchAccount(vm.account).then(angular.noop, function(error)
somethingApplication.parseErrors(error, ‘Account error: ‘);
/* a few more patches */
$q.all(somethingApplication.promises).then(function()
/* display dialog */
, angular.noop).finally(function()
postGet();
somethingApplication.promises = [];
if (somethingApplication.errors.length >= 1)
vm.errors = somethingApplication.errors;
);
somethingApplication.service.js
function somethingApplication(SomethingRepo)
var promises = [], errors = [];
var service =
promises: promises;
errors = errors;
parseErrors: parseErrors;
;
return service;
function parseErrors(error, base_string)
angular.forEach(error.data.erros, function(value_params, key_params)
this.errors.push(base_string + ‘ ‘ + key_params.replace(/_/g, ‘ ‘) + ‘ ‘ + value_params);
, this);
somethingRepo.js
function SomethingRepo(Server)
function get()
return Server.get(‘/something/application’, null, noGlobal: true);
我已经减少了文件,但它们包含更多这样的代码。 控制器的目的是为另一个网站创建或更新应用程序。在我的网站上,我有一个与另一个网站上的表单相对应的字段表单。如果您已经提交了申请,但想要更新它,您已经提交的信息将从其他网站加载。
问题是,为了创建或更新应用程序,许多不同的端点请求发布到。
在 AngularJS 中,我存储来自每个请求的 Promise,并在最后异步运行它们。在 TypeScript 和 Angular 中,我想使用 Observables 并订阅数据更改。
我该如何开始?如何从另一个 Observable 订阅 Observable 所需的参数?任何建议如何进行?
【问题讨论】:
Observable
支持 ToPromise
方法,将 Observable 转换为可调用的 Promise。如果您想保留Promise.all
方法,您可以。否则,您可以考虑使用 RxJs 建议的其他方法,例如 .concatMap
、forkJoin
等。尽可能利用async await
,这将帮助您跟踪它在迁移阶段所做的工作。
“我如何开始?如何订阅另一个 Observable 的所需参数?任何建议如何继续?”如果我理解正确,您正在寻找forkJoin
。您可以将其与 from(promise)
结合使用以创建一个可观察的对象,该可观察对象等待一组承诺解决,然后发出已解决值的列表。
我不想保留Promise
方法。你有一个具体的例子来说明我如何forkJoin
我的特定代码吗?不是我想让你做这项工作,但我很难将我读到的关于 forkJoin
的内容应用到我的代码中
这可能会有所帮助 - ***.com/questions/39319279/…
@FrankfromDenmark forkJoin 与 Promise.all 完全一样:您提供 Observables 的数组(或列表)(angular 的 HttpClient.get 返回一个Observable
默认情况下),它的回调会触发所有解析的值。 FK82 提供了上面的官方文档。看看示例 5,它非常接近您的用例。
【参考方案1】:
这是一个示例,展示了如何在场景中轻松使用可观察对象 -
你的服务应该是这样的 -
import Injectable from '@angular/core';
import AppConstants from '../../app.constants';
import HttpClient from '@angular/common/http';
@Injectable()
export class ExampleService
constructor(private appconstants: AppConstants, private http: HttpClient)
get()
return this.http.get(this.appconstants.apiUrl);
getSomethingOne()
return this.http.get(this.appconstants.apiUrl1);
getSomethingTwo()
return this.http.get(this.appconstants.apiUrl2);
然后只需在您的组件中使用它,如下所示 -
import Component from '@angular/core';
import forkJoin from 'rxjs';
import ExampleService from '../services/example.service';
@Component(
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css']
)
export class ExampleComponent
data;
dataOne;
dataTwo;
constructor(private exampleService: ExampleService)
getApplication()
const combined = forkJoin([
this.exampleService.get(),
this.exampleService.getSomethingOne(),
this.exampleService.getSomethingTwo()
]);
combined.subscribe(res =>
this.data = res[0];
this.dataOne = res[1];
this.dataTwo = res[2];
);
【讨论】:
两个问题:1) 我不能让我的服务返回一个 Observable,例如:get(): Observable<Application> return this.client.get<Application>(this.appconstants.apiUrl).pipe( map((item: any) => return Object.assign(new Application(), item); ) );
2) 我将如何使用来自 forkJoin
的结果来创建另一个请求?我可以链接它,还是应该在之后提出单独的请求?
1) 这种方法也很好,也是一种很好的做法。 2)您可以从您的函数中返回一个Observable
- getApplication()
,然后在其订阅中执行进一步的操作
这是一个参考。用于创建 observable - medium.com/@luukgruijs/…
非常感谢以上是关于将多个嵌套的 Promise 和 Promise 数组转换为 Observables的主要内容,如果未能解决你的问题,请参考以下文章