Angular 2:从订阅 http.post 获得响应后如何调用函数

Posted

技术标签:

【中文标题】Angular 2:从订阅 http.post 获得响应后如何调用函数【英文标题】:Angular 2: How to call a function after get a response from subscribe http.post 【发布时间】:2017-07-03 11:46:25 【问题描述】:

从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();

仅当我更改为:

服务: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_catagories() 是否也在使用 observable?如果是,您需要使用 .mergeMap() 运算符将 get_categories() 中的 observable 链接到 send_categories() 中的那个。如果您需要语法方面的帮助,请告诉我。 send_catagories() 没有使用 observable,请告诉我语法:return this.http.post( url, body, headers: headers, withCredentials:true) .subscribe( response => this.total_page = response.json();返回 this.total_page; , .share() ); 然后 this.get_category(1).subscribe(response=> this.callfunc(); ); 知道了。我已经用正确的语法发布了一个答案。 【参考方案1】:

您可以将回调函数添加到您的 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 但我不知道该怎么做 使用回调函数没有什么不专业的,但适合自己 在我看来,在使用 observables 时将回调传递给服务并不是一个好的模式。正如 Louis 所暗示的,它使额外的逻辑和错误处理变得丑陋。 @RobM 我只是想说你是对的。在重写同事应用程序时,我去回调地狱又回来了,现在我看到了错误!【参考方案2】:
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(); (173,69):错误 TS2339:“订阅”类型上不存在属性“订阅”。 为什么要原始语法? FRP 是关于组合流以创建一个可以订阅的有意义的 observable。 @pixelbits 我收到一条错误消息,指出.share does not exist on type Observable<any> 并且return total 不应该是return this.total?只是想弄清楚这段代码,因为我正在努力解决类似的问题。【参考方案3】:

更新您的get_categories() 方法以返回总数(包装在可观察对象中):

// 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")
    );

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

就像我在 cmets 中所说的,任何 observable 的 .subscribe() 方法都接受 3 个这样的回调:

obs.subscribe(
  nextCallback,
  errorCallback,
  completeCallback
);

它们必须按此顺序传递。你不必通过所有三个。很多时候只实现了nextCallback

obs.subscribe(nextCallback);

【讨论】:

谢谢,谢谢,谢谢!它工作完美!只有两个问题,1)在 this.send_categories(total) this.myNewTotal= total 里面我如何从“total”参数中提取数据(responde.json)? 2)我在语法中添加了“错误”: .map(response => response.json()), error => );如果我只需要在错误情况下调用 this.send_categories(total) ,我如何订阅错误? 嗯。根据您之前的代码,我认为response.json() WAS 是总数。我的意思是,我将变量命名为total,但它包含response.json() 中的任何内容;你可以随意命名这个变量。我更新了我的答案以更好地反映这一点,并向您展示如何处理错误。 我可能错过了订阅中第三个参数的要点,但我想知道您是否可以调用一个方法来完成回调? 通常这两个回调是同义词。以 HTTP 请求为例。当服务器返回数据时,nextCallback 被调用,然后紧跟在completeCallback 之后。但在不同的情况下(例如聊天系统),nextCallback 可以被多次调用(例如,对于每个聊天通知),completeCallback 永远不会被调用。 有史以来最好的解释。【参考方案4】:

您可以将 lambda 表达式编码为 subscribe 方法的第三个参数(完成时)。这里我将departmentModel变量重新设置为默认值。

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

【讨论】:

【参考方案5】:

您也可以使用新的Subject 来做到这一点:

打字稿:

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 你这是什么意思? 表示第一条语句 let subject = new Subject();由于没有主题类而给出错误。 @Pratik 你需要 rxjs 继续提及 :)

以上是关于Angular 2:从订阅 http.post 获得响应后如何调用函数的主要内容,如果未能解决你的问题,请参考以下文章

Angular 的订阅未记录完整错误

从 Angular 2 客户端到 Node.js 服务器的 HTTP POST 请求

ionic 2 angular 2 从 ion-select 中获取值以发送 http post

Angular 2 http post 作为空对象或在关键端发送

如何在 Angular 2 轮询服务中访问 .subscribe 之外的值

Angular $http POST 从 ExpressJS 获取 null