簡體   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