Angular 5可观察,完成后返回

时间:2018-07-10 14:57:55

标签: angular observable

有关Angular 5可观察对象的帮助。

我想对控制器隐藏复杂性;那就是不必让它必须订阅可观察的东西。具有服务的所有复杂性,并使其简单地将结果/有效载荷返回给组件。但显然我陷入了时间问题。我觉得这应该是一个热门的话题,但是还没有找到答案。所以也许我要去做错事了?

//in the component.ts
const allColors = this.auth.getColors(); //service call
console.log(allColors); // returns undefined

//in the service.ts
getColors() {
  var myColors = "";

  var colors = this.http.get<any>('http://localhost/Account/GetColors', httpOptions)
    .pipe(catchError(this.handleError));

  //
  colors.subscribe(
    res => {
      myColors = res.body;
    },
    error => {}
  );

  return myColors;
}

7 个答案:

答案 0 :(得分:4)

我认为您无法做您想做的事情,因为在服务中的订阅未解决之前,它不会向组件发送任何内容,在组件的执行中,它是未定义的,因为响应尚未得到响应。还没来。

这就是发明回调函数的原因。正确的方法是在要等待服务响应的组件中添加订阅。

对不起,但是我还不能使用评论,所以我不得不做出回复。希望对您有帮助

答案 1 :(得分:2)

  

所以也许我要去做错事了?

的确。使用Observable和Promises进行异步编程。我认为这是您提出此问题的唯一原因,您不完全了解它们的工作原理,因此您想将其抽象化,这是您无法做到的。另请参见How do I return the response from an asynchronous call?


也就是说,您可以使用async/await来提供同步代码的外观

component.ts

async ngOnInit() {
  const allColors = await this.auth.getColorsAsync(); //service call
  console.log(allColors); // returns color array
}

service.ts

getColorsAsync(): Promise<color[]> {
  return this.http.get<color[]>('http://localhost/Account/GetColors', httpOptions)
    .pipe(catchError(this.handleError))
    .toPromise();
}

我猜到了实际类型。理想情况下,应该在所有可能的情况下使用强类型

答案 2 :(得分:1)

您的方法何时返回?这就是您需要回答的问题,为了避免您的悬念,它将使 prior 返回myColors中充满了任何东西的东西,这就是异步编程的本质。

您需要返回可观察的对象,并在结果可用时让它通知。这种复杂性无法用您尝试的方式隐藏起来,最接近的方法是将回调函数传递到服务方法中,然后在有可用结果时调用该方法,如下所示:

getColors(callback) {
    //...

    colors.subscribe(
       res => {
           callback(res.body);
       }
       //...
    );
}

但是随后您将错过许多很酷的功能,例如能够将multiple subscribers设置为相同的可观察对象。

答案 3 :(得分:1)

您要使用Resolver并在使用服务之前路由到预加载数据。

解析器是一种异步操作,在激活其余路由之前已完成。因此,您将定义一个顶级路由,该路由不执行任何操作,但包含用于获取颜色数据的解析器。我说顶层是因为我假设这是全局应用程序数据。如果此数据是特定于功能的,则将解析器放置在正确的路由路径中。

const routes: Routes = [
    { 
       path: '',
       resolve: {
           Colors: ColorsResolver
       },
       children: [
             // your application routes here
       ]
    }
] 

ColorsResolver将从服务器获取颜色数据,然后将其分配给服务。

@Injectable()
export class ColorsResolver implements Resolve<any> {
     public constructor(private colorService: ColorService) {}

     public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
          return this.http.get<any>('http://localhost/Account/GetColors', httpOptions)
                  .do((resp)=> this.colorService.setColor(resp));;
     }
}

在服务中,您只需将值分配给属性

 @Injectable()
 public ColorService {
     public setColor(resp: any) { this._color = resp; }
     public getColor():any { return this._color; }
 }

您现在可以在解析器完成操作后多次调用getColor(),而不会阻塞它。

答案 4 :(得分:0)

与Osakr所说的不符。您将必须订阅您的组件。

在您的service.ts中

getColors(): Observable<any> {

    let urlString = 'http://localhost/Account/GetColors'

    return this.http.get(urlString);
  }

在您的组件中:

getColors() {

    this.service.getColors()
      .subscribe((colors) => {

      this.myColors = colors;

  })
}

答案 5 :(得分:0)

我认为您可以以其他方式做到

//in the component.ts
this.service.getColors(); //service call
console.log(this.service.allColors); // print the service property.  which will resolve after the oberservable resolve

//in the service.ts
@injectable()
export class Service {
  public allColors: any; //Public property to print.
  public getColors() {
    var myColors = "";

    var colors = this.http.get<any>('http://localhost/Account/GetColors', httpOptions)
    .pipe(catchError(this.handleError));

    colors.subscribe(
      res => {
         this.allColors= res.body;
      },
      error => {}
     );

    return;
  }
}

答案 6 :(得分:0)

这是我要怎么做:

this.http.get<any>('http://localhost/Account/GetColors', httpOptions)
  .pipe(catchError(this.handleError))
  .subscribe(res => {
    console.log(res.body);
  });