Ionic2-Long轮询:在更改页面时终止http.get请求

时间:2017-02-22 21:14:03

标签: http ionic2

我的服务器是在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()

1 个答案:

答案 0 :(得分:1)

我认为如果您有一个全局添加到应用的Providers部分的提供商(意味着它可以充当Singleton service),那么您可以使用以下内容:

  1. 每次调用提供程序的join()方法时,请在提供程序中检查hasAlreadyJoined布尔变量。
  2. 每次调用join()方法时,此变量都设置为true。
  3. 如果尚未调用join(),请调用它并相应地更新变量。
  4. 因此,即使每次调用MyProvider的join()方法,只有当hasAlreadyJoined为false时,此方法才会执行实际的http请求。

    为了确保每次启动MyProvider实例时它的变量都是“静态的”,应该在应用程序模块文件的 global Providers部分声明提供程序,而不是< em>页面的提供商部分。