繁体   English   中英

Angular 5 Observable,完成后返回

[英]Angular 5 Observable, return when complete

帮助Angular 5 Observables。

我想隐藏控制器的复杂性; 那就是不要让它必须订阅observable。 拥有服务中的所有复杂性,并将结果/有效负载简单地返回到组件。 但显然我陷入了时间问题。 我觉得这应该是一个受欢迎的事情/主题,但还没有找到答案。 所以也许我说错了什么?

//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;
}

我认为你不能做你想做的事情,因为直到你的服务中的订阅没有得到解决它不会向组件发送任何东西,在组件的执行中它是未定义的,因为响应尚未到来。

这就是发明回调函数的原因。 正确的方法是在组件中进行订阅,因为您希望等待服务的响应。

抱歉,我还不能使用评论,所以我不得不做出这个回复。 希望能帮助到你

所以也许我说错了什么?

确实。 使用Observables和Promises包含异步编程。 我相信这是你提出这个问题的唯一原因,你并不完全明白它们是如何工作的,所以你想把它抽象出来,这是你不能做的事情。 另请参见如何从异步调用返回响应?


那说你可以使用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();
}

我猜到了实际的类型。 理想情况下,您应尽可能使用强类型

你的方法什么时候回来? 这是你需要回答的问题,并且为了避免 myColors充满任何东西之前它会返回的悬念,这就是异步编程的本质。

您需要返回observable并在结果可用时通知您。 这种复杂性无法以您尝试的方式隐藏,您可以获得的最接近的是将回调函数传递给您的服务方法,然后在结果可用时调用它们,如下所示:

getColors(callback) {
    //...

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

但是你会错过许多很酷的功能,例如能够拥有同一个observable的多个订阅者

您希望在使用服务之前使用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()而不会阻塞它。

关闭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;

  })
}

我想你可以用不同的方式做到这一点

//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;
  }
}

我是这样做的:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM