Angular 2 - 直接从 Observable 返回数据

Posted

技术标签:

【中文标题】Angular 2 - 直接从 Observable 返回数据【英文标题】:Angular 2 - Return data directly from an Observable 【发布时间】:2016-10-18 10:23:30 【问题描述】:

我一直在努力解决这个问题,但我能够阅读的任何文档都无法回答我的问题。

我有一个服务直接与 API 对话并返回一个可观察的事件,在正常情况下我会订阅并使用数据做我想做的事情,但是在使用来自 restful 服务的请求的辅助服务中,我需要能够从请求中返回值。

getSomething() 
    return this._restService.addRequest('object', 'method').run()
        .subscribe(
            res => 
                res;
            ,
            err => 
                console.error(err);
            
        );


returnSomething() 
    return this.getSomething();

在上面的快速示例中,我想知道是否有任何方法可以在returnSomething() 中从getSomething() 返回res。如果以这种方式无法实现,还有什么替代方法?我要补充一点,_restService 非常依赖,我真的不想开始搞砸了。

【问题讨论】:

你在哪里使用returnSomething()?您知道这是一个异步操作,因此您无法立即“获得”结果。您也许可以在returnSomething() 中订阅(res),但我不知道这是否实用。 上面的示例将包含在一个服务中,并且对该方法的调用将在多个组件中,这就是为什么我只想返回 res 值,因为它会节省很多一点代码。我还需要能够比较两种或多种类似方法的结果。 【参考方案1】:

由于 http 调用等是异步的,因此您会得到一个 Observable 而不是返回的同步值。您必须订阅它,并在其中的回调中获取数据。没有办法解决这个问题。

一种选择是将您的逻辑放在subscribe 调用中

getSomething() 
    return this._restService.addRequest('object', 'method').run()
        .subscribe(
            res => 
                // do something here
                res;
            ,
            err => 
                console.error(err);
            
        );

但我喜欢这样做的方式是添加一个回调,从外部注入逻辑(可能是一个组件,也可能是另一个服务):

getSomething(callback: (data) => void) 
    return this._restService.addRequest('object', 'method').run()
        .subscribe(
            res => 
                callback(res);
            ,
            err => 
                console.error(err);
            
        );

在您的组件中或任何地方:

this._yourService.getSomething((data) => 
    // do something here
    console.log(data);
);

【讨论】:

绝对是一种思考使用服务的新方式,结果证明这正是我们所需要的! 我来到这里大概是因为 Observable 关键字。我需要做类似的事情。什么类型的服务有方法 .run()?我不能在常规的 Angular 2 http 服务上使用它。谢谢 花了大约几个小时来找出错误。谢谢你的回答。 主题行为如何【参考方案2】:

我遇到了类似的问题。我的解决方案是使用 .toPromise() 将 observable 转换为 promise(并使用 async - await 来返回它并捕获错误)。您可以将您的代码转换为:

 async getSomething() 
     try
         return await this._restService.addRequest('object', 'method').run().toPromise()
       catch (err)
       console.error(err);
	  
  

【讨论】:

这不是最初问题的解决方案。您不会以这种方式返回数据,而是返回 Promise,并且您仍然必须“订阅”它(使用 then)才能获得最终数据。【参考方案3】:

我自己没有使用过这个,但我相信理论上它应该可以工作(:

// service.ts
getSomething() 
  let subject: Subject = new Subject();
  this._restService.addRequest('object', 'method').run()
    .subscribe(subject);
  return subject;


// this can be removed (;
returnSomething() 
  return this.getSomething();


// component.ts
ngOnInit() 
  this.service.returnSomething()
    .subscribe(res => console.log(res), err => console.log(err));

查看subject docs 了解更多信息。您可以使用不同类型的主题,例如 BehaviorSubject 具有您可以访问的 value 属性...

ngOnInit() 
  // if you use BehaviorSubject
  this.service.returnSomething().value

这是working plunker...

【讨论】:

这行不通,因为主题在您从订阅中获取数据之前已返回。 @rinukkusu 是的,对于初始值,应该在之后工作。您可以在订阅 observable 之前为 BehaviourSubject 设置初始值...或 .filter(Boolean)。 ..

以上是关于Angular 2 - 直接从 Observable 返回数据的主要内容,如果未能解决你的问题,请参考以下文章

Angular RxJS入门笔记 (Observable可观察对象Subscribe订阅Observer观察者Subscription对象)

html 使用AJAX POST请求来调用控制器操作(在页面加载时和在下拉列表中选择项目时),获取返回的布尔值,设置observabl

如何直接从您的 Angular 项目中调用 Firebase Cloud Function

Angular 2如何将变量从父组件传递到路由器出口

从 Lumen 5.2 控制器端点提供 Angular 5 SPA 时的路由问题

Angular 2:从子组件直接发射到父组件的脚本文件