Angular 2:如何在收到subscribe http.post响应后调用函数

45

我需要在从HTTP POST请求中获取数据后调用一个方法。

服务:request.service.TS

get_categories(number){
 this.http.post( url, body, {headers: headers, withCredentials:true})
    .subscribe( 
      response => {
        this.total = response.json();

      }, error => {
    }
  ); 

}

组件:categories.TS

search_categories() {

this.get_categories(1);
//I need to call a Method here after get the data from response.json() !! e.g.: send_catagories();
}

只有当我更改为:

service: request.service.TS

get_categories(number){
 this.http.post( url, body, {headers: headers, withCredentials:true})
    .subscribe( 
      response => {
        this.total = response.json();
        this.send_catagories(); //here works fine

      }, error => {
    }
  ); 

}

但我需要在调用this.get_categories(1);后在组件内部调用send_catagories()方法,就像这样:

组件:categories.TS

search_categories() {

this.get_categories(1);
this.send_catagories(response);
}
我做错了什么?

send_categories() 方法是否也使用了 Observable?如果是的话,你需要使用 .mergeMap() 操作符将 get_categories() 返回的 Observable 与 send_categories() 中的 Observable 进行链式操作。如果需要语法方面的帮助,请告诉我。 - AngularChef
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Louise
1
明白了。我已经发布了一篇带有正确语法的答案。 - AngularChef
5个回答

60

将您的 get_categories() 方法更新为返回总数(包装在 observable 中):

// Note that .subscribe() is gone and I've added a return.
get_categories(number) {
  return this.http.post( url, body, {headers: headers, withCredentials:true})
    .map(response => response.json());
}
在`search_categories()`函数中,你可以订阅由`get_categories()`返回的可观察对象(或者你可以通过链式调用更多的RxJS操作符来进行转换)。
// send_categories() is now called after get_categories().
search_categories() {
  this.get_categories(1)
    // The .subscribe() method accepts 3 callbacks
    .subscribe(
      // The 1st callback handles the data emitted by the observable.
      // In your case, it's the JSON data extracted from the response.
      // That's where you'll find your total property.
      (jsonData) => {
        this.send_categories(jsonData.total);
      },
      // The 2nd callback handles errors.
      (err) => console.error(err),
      // The 3rd callback handles the "complete" event.
      () => console.log("observable complete")
    );
}

请注意,您只需要在最后订阅一次

如我在评论中所说,任何可观察的.subscribe()方法接受三个回调函数,如下所示:

obs.subscribe(
  nextCallback,
  errorCallback,
  completeCallback
);

这些参数必须按照指定的顺序传递。不需要全部传递三个参数,很多时候只需要实现nextCallback参数:

obs.subscribe(nextCallback);

谢谢,谢谢,谢谢!它完美地工作了!只有两个问题,1)在this.send_categories(total){ this.myNewTotal= total }中,我如何从“total”参数中提取数据(response.json)?2)我已经将“error”添加到语法中:.map(response => response.json()), error => { });如果我只需要在错误情况下调用this.send_categories(total),我该如何订阅错误? - Louise
嗯。根据你之前的代码,我认为response.json()就是总数。我的意思是,我将变量命名为total,但它包含在response.json()中的任何内容;你可以随意更改这个变量的名称。我的答案已经更新以更好地反映这一点,并向你展示如何处理错误。 - AngularChef
我可能没有理解subscribe中第三个参数的意义,但我想知道是否可以调用一个方法来完成回调? - Winnemucca
1
往往这两个回调函数是同义词。以HTTP请求为例,当服务器返回数据时,会先调用nextCallback,然后立即调用completeCallback。但在不同的情况下(例如聊天系统),nextCallback可能会被多次调用(例如每个聊天通知都会调用一次),而completeCallback可能永远不会被调用。 - AngularChef
如果您使用Observable.create()创建了一个可观察对象,您可以使用observer.complete()来完成它。如果您有一个Subject,您可以调用subject.complete()。最后,一些操作符会触发可观察对象的完成,例如obs.take(1),它会在发出一个值后完成可观察对象。 - AngularChef
1
有史以来最好的解释。 - yas

10
你可以在get_category(...)参数列表中添加回调函数。
例如:
 get_categories(number, callback){
 this.http.post( url, body, {headers: headers, withCredentials:true})
    .subscribe( 
      response => {
        this.total = response.json();
        callback(); 

      }, error => {
    }
  ); 

}

然后你只需像这样调用 get_category(...):

this.get_category(1, name_of_function);

谢谢,我会尝试的。但我的想法是使用更专业的方法来捕获响应。例如:get_category(1).then 或者一个 observable,但我不知道如何实现。 - Louise
使用回调函数并不会让你看起来不专业,但是随你便。 - Gab
4
在我的观点中,当使用可观测对象时,将回调函数传递给服务是不好的模式。正如路易斯所暗示的那样,它会使附加的逻辑和错误处理变得复杂难懂。 - RobM
2
@RobM 我只是想说你是对的。在重写同事的应用程序时,我走进了回调地狱,现在我意识到我的错误! - Gab

6

在subscribe方法的第三个参数(on complete)中,你可以将代码编写为lambda表达式。这里我将departmentModel变量重置为默认值。

saveData(data:DepartmentModel){
  return this.ds.sendDepartmentOnSubmit(data).
  subscribe(response=>this.status=response,
   ()=>{},
   ()=>this.departmentModel={DepartmentId:0});
}

2
你可以使用一个新的 Subject 来完成这个操作: Typescript:
let subject = new Subject();

get_categories(...) {
   this.http.post(...).subscribe( 
      (response) => {
         this.total = response.json();
         subject.next();
      }
   ); 

   return subject; // can be subscribed as well 
}

get_categories(...).subscribe(
   (response) => {
     // ...
   }
);

@Pratik,你是什么意思? - Willi Mentzel
意思是,第一条语句 let subject = new Subject(); 报错,因为没有 subject 类。 - Pratik Joshi
@Pratik,你需要使用rxjs来实现。 - Willi Mentzel
不断提醒:) - Pratik Joshi

1
get_categories(number){
 return this.http.post( url, body, {headers: headers, withCredentials:true})
      .map(t=>  {
          this.total = t.json();
          return total;
      }).share();
  );     
}

那么

this.get_category(1).subscribe(t=> {
      this.callfunc();
});

是的!这就是我想要的,我如何保留旧语法而不使用“.map”?例如:return this.http.post(url,body,{headers:headers,withCredentials:true}) .subscribe( response => { this.total = response.json(); return total; })。share(); - Louise
(173,69): 错误 TS2339: 类型'Subscription'上不存在属性 'subscribe'。 - Louise
你为什么想要原始语法?FRP是关于将流组合成一个有意义的可观察对象,可以订阅它。 - pixelbits
@pixelbits 我遇到了一个错误信息,提示“Observable<any> 类型上不存在.share”,还有,return total 不应该是 return this.total 吗?我只是试图理解这段代码,因为我正在苦苦挣扎处理类似的问题。 - Alfa Bravo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接