我尝试使用RxJS从Promise链中创建Rx.Observable
。与this question的区别在于我的Promise数量未知,而且每个Promise都取决于前一个Promise的结果。
基本上我有一系列页面,与"下一页"链接。
我想要的功能是:
我尝试了以下内容:
private getPages<T>(firstPromise: PromiseLike<IODataCollectionResult<T>>): Rx.Observable<T> {
let observable = Rx.Observable.create<T>(async obs => {
let page = await firstPromise;
page.value.forEach(v => obs.onNext(v));
while (page['@odata.nextLink']) {
let nextPageUrl = <string>page['@odata.nextLink'];
let nextPagePromise = <PromiseLike<IODataCollectionResult<T>>>this.resource(nextPageUrl).get().$promise;
page = await nextPagePromise;
page.value.forEach(v => obs.onNext(v));
}
obs.onCompleted();
});
return observable;
}
(IODataCollectionResult
是一个OData结果,其中&#39; @ odata.nextLink&#39;是下一页的网址,而.value是一个值数组)
问题我无法用TypeScript编译它,它给了我一个错误:
类型的参数&#39;(obs:Observer)=&gt;诺&#39;不能分配给&#39;(观察者:观察者)=&gt;类型的参数。无效|功能| IDisposable的&#39;
这是有道理的,因为异步函数返回Promise<void>
,而不是void
。
这是否意味着我不能对Rx.Observable.create()使用async / await?如何将一系列Promise链接到一个Observable?
答案 0 :(得分:1)
你可以将async function
包裹在使结果无效的东西中:
function toVoid<A>(fn: A => Any): A => Void {
return x => void fn(x)
}
(原谅我对TypeScript缺乏了解,但我希望你能猜出它应该做什么)
有了这个,你应该可以打电话了
let observable = Rx.Observable.create<T>(toVoid(async obs => {
…
}));
但也许你不应该这样做。不要丢弃承诺,而是使用它来附加相应的错误处理程序:
let observable = Rx.Observable.create<T>(obs => {
(async () => {
…
}()).catch(err => {
obs.onError(err);
});
});
答案 1 :(得分:0)
问题是使用.then()+递归解决的,没有async / await:
private getPages<T>(initialPromise: PromiseLike<IODataCollectionResult<T>>): Rx.Observable<T> {
return Rx.Observable.create<T>(obs => {
const getPage = (promise: PromiseLike<IODataCollectionResult<T>>) => {
promise.then(page => {
page.value.forEach(v => obs.onNext(v));
if (page['@odata.nextLink']) {
let nextPageUrl = <string>page['@odata.nextLink'];
let nextPagePromise = <PromiseLike<IODataCollectionResult<T>>>this.resource(nextPageUrl).get().$promise;
getPage(nextPagePromise);
}
else {
obs.onCompleted();
}
});
}
getPage(initialPromise);
});
}