如何在订阅Angular 4中返回值
Posted
技术标签:
【中文标题】如何在订阅Angular 4中返回值【英文标题】:How to return value inside subscribe Angular 4 【发布时间】:2018-09-11 07:19:27 【问题描述】:我是 angular 的 observables 新手。我有一个问题,我想在订阅方法中返回一个值。我有
以下方法(getFirebaseData(idForm:string):observable <any[]>
):
getTotalQuestions(idForm:string)
let totalQuestions:number;
this.getFirebaseData(idForm+"/Metadatos")
.subscribe(items =>
items.map(item =>
totalQuestions=item.Total;
console.log(totalQuestions);
);
);
console.log(totalQuestions);
return totalQuestions;
第一个console.log(totalQuestions)
打印4,但第二个console.log(totalQuestions)
打印undefined。
我知道订阅是一个异步操作,因此第二个console.log(totalQuestions)
(“为了编写代码”)打印未定义,但在订阅方法完成后我找不到返回变量的方法。现在,如果我将订阅更改为地图:
getTotalQuestions(idForm:string)
let totalQuestions:number;
this.getFirebaseData(idForm+"/Metadatos")
.subscribe(items =>
items.map(item =>
totalQuestions=item.Total;
console.log(totalQuestions);
);
);
console.log(totalQuestions);
return totalQuestions;
第一个console.log(totalQuestions)
不打印任何内容,第二个console.log(totalQuestions)
打印未定义。我不明白为什么会这样。
希望你能帮我澄清一下我不明白的概念。谢谢!
【问题讨论】:
请查看以下URL 【参考方案1】:你不能像那样直接返回totalQuestions,你需要使用一个主题来实现。
getTotalQuestions(idForm:string): Observable<string>
let totalQuestions:number;
var subject = new Subject<string>();
this.getFirebaseData(idForm+"/Metadatos")
.subscribe(items =>
items.map(item =>
totalQuestions=item.Total;
console.log(totalQuestions);
subject.next(totalQuestions);
);
);
return subject.asObservable();
用法:getTotalQuestion(idForm).subscribe((r)=>console.log(r))
【讨论】:
我们必须明白,我试图做的是一个反模式,不能强制异步任务同步,因此,包含 observable 的方法通常返回另一个 observable 或什么也不返回.因此,我接受这个答案作为解决方案。非常感谢! @Rajani Kanth 你能检查一下这个问题吗?和上面的问题一样! ***.com/questions/54873434/… 你是冠军!谢谢 谢谢!看起来很疯狂,对于所有 rxjs 方法,都没有像 angularjs 中的延迟承诺那样工作。不过这很好用。 @Rajani:它可以工作,但我想从服务而不是组件返回内部订阅数据,你能告诉我该怎么做吗?【参考方案2】:Observable 在你订阅它时运行,订阅返回的总是一个订阅对象,比如 setInterval。第一个示例:因为这是一个异步调用,所以第二个 console.log 在执行之前不会等待订阅完成。
getTotalQuestions(idForm: string)
let totalQuestions: number;
return this.getFirebaseData(idForm + "/Metadatos").pipe(
map(items =>
items.map(item =>
totalQuestions = item.Total;
console.log(totalQuestions);
);
));
getTotalQuestions('231').subscribe(console.log)
【讨论】:
所以这里没有返回值?【参考方案3】:I made a live example。 您无需触发订阅即可对数组进行转换或将某些对象减少为单个值,这是我的方法。 您的服务
getTotalQuestions(idForm: string): Observable<any>
return this.getFirebaseData(`$idForm/Metadatos`)
.pipe(map(items => items
.map(item => item.Total)
.reduce((a, b) => a+b), 0));
您的组件
this.service.getTotalQuestions('id')
.subscribe(totalQuestions => console.log(totalQuestions));
【讨论】:
【参考方案4】:为了解决这个问题,我将创建一个属性 totalQuestions$
一个 observable
在 TS 文件中
totalQuestions$ = this.getFirebaseData(idForm + "/Metadatos").pipe(
map(items => items.reduce((prev, Total) => prev + Total), 0)))
)
现在你可以在你的模板中使用async
pipe
<span> totalQuestions$ | async </span>
如果您想在 TS 文件中使用该变量,则可以使用组合运算符,如 forkJoin
或 combineLatest 来访问该值
newVariable$ = combineLatest([totalQuestions$, ...]).pipe(
map(([totalQuestions, ... ]) =>
// Perform an operation here and return a value
)
)
【讨论】:
以上是关于如何在订阅Angular 4中返回值的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Angular 4+ 中取消/取消订阅所有挂起的 HTTP 请求
在使用带有 Angular 的 FromEvent RxJS 订阅输入标签值更改时如何避免使用“任何”?