所以,我有这个服务,它首先从另一个模块调用一个函数,该函数基本上从外部 api 返回一个 url 列表。该服务必须http.get
从该列表中的所有 url(每个 url 返回相同格式的 json 对象)然后返回一个可观察的值,然后我可以在 Angular component
中使用它。我的服务代码如下:
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Client } from 'external-api';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
let client = new Client();
@Injectable()
export class GbDataService {
constructor(private _http: Http) {
}
getGBData(): Observable<any> {
client.fetchUrls("").then(resp=> {
resp.forEach(url => {
//this._http.get(url).map(res => res.json);
// Create a single observable for every http response
});
}).catch(function(err){
console.log(err.message);
});
//return observable
};
}
http.get
返回并 Observable<Response>
type 但我找不到一种方法来为所有 http.get 响应创建并返回一个 Observable。如何才能做到这一点 ?我应该创建一个可观察数组吗 push()
所有get
我得到数组的响应?
编辑:对于我来说,响应是一个一个地发出还是一次全部发出并不重要,但必须只有一个 Obeservable 发出所有 http.get
的响应。请求。
进一步编辑:这是我的 fetchURLs 方法:
fetchURLs(): Promise<any> {
return new Promise((resolve, reject) => {
let _repos: Array<any>;
//scrapeTrendingRepos() is from https://github.com/rhysd/node-github-trend
scraper.scrapeTrendingRepos("").then(repos => {
repos.forEach(repo => {
let url = `https:api.github.com/repos/${repo.owner}/${repo.name}`;
_repos.push(url);
});
resolve(_repos);
}).catch(err => {
reject(err);
});
})
};
我是否在fetchURLs()
中实现了Promise对吗??
最佳答案
那么,您发出请求并返回一组 URL,然后您想要获取所有 URL 并从中获取一个响应?
这些都是 RxJS 擅长的事情。
@Injectable()
export class GbDataService {
constructor(private _http: Http) {
}
getGBData(): Observable<any> {
return Observable
.fromPromise(client.fetchUrls()) // returns Observable<array>
.switchMap( urls => {
// convert your list of urls to a list of http requests
let urlRequests = urls.map( url => http.get(url) );
// combineLatest accepts an array of observables,
// and emits an array of the last results of each of the observables
// but the first emit only happens after every single observable
// has emitted its first result
// TLDR: combineLatest takes an array of Observables
// and will emit an array of those observable emissions // after all have emitted at least once
return Observable.combineLatest(urlRequests);
})
}).catch(function(err){
console.log(err.message);
});
//return observable
};
}
更多信息:
阅读combineLatest observable。在这种情况下,它完成了您想要的等待所有可观察参数在发出单个数组之前发出的任务。但是,如果您的可观察参数也多次发出,它可能不会达到您的预期,您可能想尝试不同的运算符,例如 forkJoin 或 zip。
另外
您可能想要使用 switchMap 而不是 flatMap - 如果有新的 url 获取请求通过,switchMap 将在发送新请求列表之前取消当前正在处理的所有请求。
进一步编辑
虽然您的 fetchURLs 实现可以在当前版本中工作,但如果您愿意,可以利用 Promise 的工作原理来稍微简化您的方法。在“Promise-land”中,then
处理程序还返回一个 Promise
,第二个 Promise
将解析为您从 then 返回的任何值。 code>then
处理程序(这是基本的 promise 链概念)。利用这些知识,您可以简化您的方法:
fetchURLs(): Promise<any> {
//scrapeTrendingRepos() is from https://github.com/rhysd/node-github-trend
return scraper.scrapeTrendingRepos("").then(repos => {
// since repos is an array, and you wish to transform each value
// in that array to a new value, you can use Array.map
return repos.map( repo => `https:api.github.com/repos/${repo.owner}/${repo.name}`);
});
}
关于javascript - 可观察 Angular 2 的多个响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43119505/