我的服务器是在Node.js上开发的。这是一个长轮询服务(例如聊天):它提供以下API:
join() //listening for new events
align(fromId) //retrieving events from an id
send(data) //creating an event
长轮询由join()实现:它发送请求,服务器在有新事件时应答。
Ionic2的前端
共有2页:Page
1和Page2
。其中Page2
是我的事件的查看者,其中长轮询通信正在运行。
所以我从Page1
开始,然后我推()第二页Page2
。到现在为止一切正常;但是,如果我弹出()Page2
然后再次推送()Page2
,那么我可以看到仍然运行我join()
的上一个实例的Page2
。此行为会创建重复的join():如果我多次推送/弹出Page2
,我将与服务器进行许多长轮询通信。
所以我试图在离开页面时找到一种方法来杀死join()
实例,这是一个HTTP.get请求。
现在让我们看看我的代码。 这是我负责与服务器通信的Ionic2的提供者
import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
@Injectable()
export class MyProvider {
...
constructor(private http: Http) {
this.token_access = null;
this.token_room = null;
}
...
join(){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('x-access-token',this.getToken());
return Observable.create(observer =>{
this.http.get('/localhost/chat/'+this.room,{headers : headers})
.map(res => res.json())
.subscribe(
data=>{
observer.next(data);
},
(err) =>{
observer.error(err);
}
);
})
}
send(message){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('x-access-token',this.getToken());
headers.append('x-chat-token',this.getRoomToken());
return Observable.create(observer =>{
this.http.post('/localhost/chat/'+this.room+'/send', JSON.stringify({
event: message
}),{headers : headers})
.map(res => res.json())
.subscribe(
data=>{
observer.next(data);
},
(err) =>{
observer.error(err);
}
);
})
}
align(from){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('x-access-token',this.getToken());
headers.append('x-chat-token',this.getRoomToken());
return Observable.create(observer =>{
this.http.post('/localhost/chat/'+this.room+'/align', JSON.stringify({
fromId: from
}),{headers : headers})
.map(res => res.json())
.subscribe(
data=>{
observer.next(data);
},
(err) =>{
observer.error(err);
}
);
})
}
}
Page1
只需使用调用以下代码(page1.ts)的按钮推送Page2
:
...
export class Page1 {
...
constructor(public navCtrl: NavController, public myProviderService: MyProvider) {
}
.....
toPage2(){
this.navCtrl.push(Page2);
}
我的Page2
由以下代码实现:
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { MyProvider } from '../../providers/myprovider';
import { Event } from '../../components/event';
@Component({
selector: 'page-chat',
templateUrl: 'chat.html'
})
export class ChatPage {
eventsList: Array<Event>;
message: any;
last_event: any;
msg: any;
constructor(public navCtrl: NavController, public myProviderService: MyProvider) {
this.last_event = -1;
this.join();
this.eventsList= new Array();
}
join(){
this.myProviderService.join().subscribe(
(data)=>{
if(data.success){
this.last_event = this.last_event + 1;
if(this.last_event == data.event.id){
//up to now all events are correctly received
this.eventsList.push(data.event);
}else{
//some events are missing
this.last_event = this.last_event - 1;
this.align();
}
this.join();
}else{
this.message=data.message;
//TBD sleep....
//this.join();
}
},
(err) => {
this.message="Connectivity with server Lost...";
//TBD sleep....
//this.join();
});
}
align(){
this.myProviderService.align(this.last_event + 1).subscribe((data)=>{
if(data.success){
for (var i=0;i<data.events.length;i++) {
this.eventsList.push(new Event(data.events[i].id,data.events[i].data,data.events[i].user));
this.last_event = this.last_event + 1;
};
}else{
this.message=data.message;
}
},
(err) => {
this.message="Failure receiving messages";
});
}
send(): void{
this.myProviderService.send(this.msg).subscribe((data)=>{
if(data.success){
this.msg='';
}else this.message=data.message;
},
(err) => {
this.message="Error while authenticating";
})
}
ionViewDidLoad() {
}
ionViewDidEnter() {
}
}
回到我的问题:
如果不使用,我怎么能杀死我的Page2的join()
(杀死HTTP.get请求)实例,以防止重复join()
?
答案 0 :(得分:1)
我认为如果您有一个全局添加到应用的Providers部分的提供商(意味着它可以充当Singleton service),那么您可以使用以下内容:
因此,即使每次调用MyProvider的join()方法,只有当hasAlreadyJoined为false时,此方法才会执行实际的http请求。
为了确保每次启动MyProvider实例时它的变量都是“静态的”,应该在应用程序模块文件的 global Providers部分声明提供程序,而不是< em>页面的提供商部分。