2016-11-24 27 views
11

Tôi đang gặp một số sự cố khi thực hiện các cuộc gọi lồng nhau. Bằng cách đó, tôi có nghĩa là một cuộc gọi đến một dịch vụ http truy xuất một người dùng, sau đó nhận được id từ người dùng để thực hiện cuộc gọi http khác và cuối cùng hiển thị kết quả trên màn hình.Cách thực hiện các cuộc gọi có thể quan sát lồng nhau trong Angular2

1) HTTP GET 1: có được người dùng

2) HTTP GET 2: có được sở thích của người dùng thông qua một định danh duy nhất như một tham số

này chuyển thành đoạn mã sau vào phần Blah.ts:

phiên bản 1 - mã này không hiển thị bất cứ điều gì

ngOnInit() { 
     this.userService.getUser() 
      .flatMap(u => { 
       this.user = u; // save the user 
       return Observable.of(u); // pass on the Observable 
      }) 
      .flatMap(u => this.userService.getPreferences(this.user.username)) // get the preferences for this user 
      .map(p => { 
       this.preferences = p; // save the preferences 
      }); 
    } 

phiên bản 2 - mã này hoạt động nhưng dường như cách tiếp cận sai với tôi:

this.userService.getUser().subscribe(u => { 
      this.user = u; 
      this.userService.getPreferences(this.user.username).subscribe(prefs => { 
       this.preferences = prefs; 
      }); 
     }); 

Và đây là mẫu:

<h3>User</h3> 

<div class="row col-md-12"> 
    <div class="col-md-6"> 
     <div class="panel panel-default"> 
      <div class="panel-heading"> 
       <h3 class="panel-title">User details</h3> 
      </div> 
      <div class="panel-body"> 
       <table class="table table-condensed"> 
        <thead> 
         <tr> 
          <th>Username</th> 
          <th>Full Name</th> 
          <th>Enabled</th>         
         </tr> 
        </thead> 
        <tbody> 
         <tr> 
          <td>{{user?.username}}</td> 
          <td>{{user?.fullName}}</td> 
          <td>{{user?.enabled}}</td>       
         </tr> 
        </tbody> 
       </table> 
      </div> 
     </div> 
    </div> 
    <!-- end of col 1--> 

    <div class="col-md-6"> 
     <div class="panel panel-default"> 
      <div class="panel-heading"> 
       <h3 class="panel-title">User preferences</h3> 
      </div> 
      <div class="panel-body"> 
       <table class="table table-condensed"> 
        <thead> 
         <tr> 
          <th>Language</th> 
          <th>Locale</th> 
         </tr> 
        </thead> 
        <tbody> 
         <tr> 
          <td>{{preferences?.preferences?.get('language')}}</td> 
          <td>{{preferences?.preferences?.get('locale')}}</td> 
         </tr> 
        </tbody> 
       </table> 
      </div> 
     </div> 
    </div> 
    <!-- end of col 2--> 

</div> 
<!-- end of row 1--> 

Tôi không nghĩ có bất kỳ điểm nào trong hiển thị dịch vụ , mà chỉ đơn giản làm cho http get() cuộc gọi như:

http.get('http://blablah/users/') 
     .map((response) => response.json()) 

Xin gợi ý đó là cách tiếp cận làm việc tốt nhất để xác định một chuỗi các Observables.

+0

"tác phẩm mã này, nhưng dường như là cách tiếp cận sai đối với tôi ..." Tại sao? –

Trả lời

14

Bạn nên đọc lên trên các nhà khai thác rxjs của một chút. Ví dụ của bạn rất chi tiết và sử dụng flatMapmap theo cách mà chúng không được sử dụng. Ví dụ đầu tiên của bạn không thể làm việc, bởi vì bạn không đăng ký vào Observable.

này sẽ làm những gì bạn cần:

ngOnInit() { 
    this.userService.getUser() 
     .do(u => this.user = u) //.do just invokes the function. does not manipulate the stream, return value is ignored. 
     .flatMap(u => this.userService.getPreferences(u.username)) 
     .subscribe(p => this.preferences = p); 
} 
+0

+1 - Tôi chỉ có một câu hỏi, sử dụng giải pháp này, cách tốt nhất để xử lý các lỗi có thể được ném bởi một trong hai cuộc gọi dịch vụ là gì? Tôi hiểu rằng bạn có thể thêm một trình xử lý lỗi trong phương thức đăng ký; tuy nhiên, điều đó sẽ chỉ áp dụng cho cuộc gọi dịch vụ getPreferences. Cách sạch nhất để ghi lại cả hai cuộc gọi ở một điểm là gì? giả sử rằng cả hai đều nên được xử lý theo cách tương tự. Cảm ơn – Sam

+2

bất kỳ lỗi nào sẽ được chuyển xuống hết đường ống – j2L4e

+1

cảm ơn bạn đã làm rõ! Bây giờ tôi hiểu rõ hơn về cách thức hoạt động này, cảm ơn bạn. – Sam

2

bạn đang đúng, đăng ký cao lồng nhau là sai ...

flatMap là đúng

này sẽ giúp

https://embed.plnkr.co/mqR9jE/preview

hoặc đọc hướng dẫn này

https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

một số mã ...

// responseStream: stream of JSON responses 
var responseStream = requestStream 
    // We use flatMap instead of map to prevent this stream being a metastream - i.e. stream of streams 
    .flatMap(requestUrl => { 
    // Convert promise to stream 
    return Rx.Observable.fromPromise($.getJSON(requestUrl)); 
    }).publish().refCount(); // Make responseStream a hot observable, prevents multiple API requests 
// see https://gist.github.com/staltz/868e7e9bc2a7b8c1f754#gistcomment-1255116 

yêu cầu tại đây URL là đầu vào được phát ra từ một luồng khác/Có thể quan sát.

nay đăng ký vào responseStream

1

Các phiên bản 1 là tốt nhất và nên công trình, bạn chỉ cần quên để đăng ký:

ngOnInit() { 
    this.userService.getUser() 
     .flatMap(u => { 
      this.user = u; // save the user 
      return Observable.of(u); // pass on the Observable 
     }) 
     .flatMap(u => this.userService.getPreferences(this.user.username)) // get the preferences for this user 
     .map(p => { 
      this.preferences = p; // save the preferences 
     }) 
     .subscribe(); 
} 
2

Được rồi, vì vậy sau một ngày vật lộn và biên dịch thông tin từ Internet ở đây là những gì tôi biết về chaining quan sát (Calling quan sát trong một chuỗi - cái khác):

Tôi đang làm việc một trang web Angular2 (4) và trang web này sử dụng API phụ trợ java để nhận/đặt/sửa đổi thông tin trong cơ sở dữ liệu.

Vấn đề của tôi là tôi phải thực hiện hai lệnh gọi API (HTTP POST) theo thứ tự trả về các Observables (RxJS).

Tôi có Operation1 và Operation2. Thao tác 2 Nên thực thi sau khi hoàn thành thao tác1. enter image description here

Variant1 -> Lúc đầu, tôi đã làm điều đó một bên khác (như chức năng lồng nhau trong javascript):

 this.someService.operation1(someParameters).subscribe(
     resFromOp1 => { 
      this.someService.operation2(otherParameters).subscribe(
      resFromOp2 => { 
       // After the two operations are done with success 
       this.refreshPageMyFunction() 
      }, 
      errFromOp2 => { 
       console.log(errFromOp2); 
      } 
     ); 
     }, 
     errFromOp1 => { 
      console.log(errFromOp1); 
     } 
    ); 

Mặc dù mã này là legit và làm việc, tôi đã yêu cầu để chuỗi những quan sát một sau một cách khác như cách nó được thực hiện với các hàm async với Promises. Một cách là chuyển đổi Quan sát thành Lời hứa.

cách Onother là sử dụng RxJS flatMap:

Variant2 -> Một cách khác là để làm điều này với flatMap mà như tôi đã hiểu tương tự như lời hứa thì:

this.someService.operation1(someParameters) 
    .flatMap(u => this.someService.operation2(otherParameters)) 
    .subscribe(function(){ 
     return this.refreshPageMyFunction() 
     }, 
     function (error) { 
     console.log(error); 
     } 
    ); 

Variant3 -> Cùng với chức năng mũi tên:

this.someService.operation1(someParameters) 
    .flatMap(() => this.someService.operation2(otherParameters)) 
    .subscribe(() => this.refreshPageMyFunction(), 
     error => console.log(error) 
    ); 

Các phương pháp mà trở lại quan sát cơ bản sau đây:

operation1(someParameters): Observable<any> { 
    return this.http.post('api/foo/bar', someParameters); 
    } 

    operation2(otherParameters): Observable<any> { 
    return this.http.post('api/some/thing', otherParameters); 
    } 

Tài nguyên bổ sung và ý kiến ​​hữu ích:

This post approved answer by @j2L4e: https://stackoverflow.com/a/40803745/2979938 

https://stackoverflow.com/a/34523396/2979938 

https://stackoverflow.com/a/37777382/2979938 
+0

Tôi thích câu trả lời này, tuy nhiên, hầu hết các trường hợp chuỗi không đồng bộ liên quan đến việc truyền tham số từ operation1 đến operation2, bạn có thể thêm nó vào ví dụ của bạn thay vì các tham số khác không? Tôi hiểu rõ các ví dụ của bạn, nhưng điều này sẽ làm cho chúng hoàn chỉnh. – Undrium

Các vấn đề liên quan