简体   繁体   中英

How to send events from nodeJS/express to angular

I have a long running transaction, and I would like to inform the client of the progress. My front end is Angular 4 and backend is nodeJS/Express . The client initiates the transaction via HTTP Post . Angular does provide a facility to listen to event progress . https://angular.io/guide/http#listening-to-progress-events

My question is, how can I send events from my express App to Angular app? As of the moment I don't want to use sockets.io .

Listening to upload progress events is actually a client-side feature. What it does behind the scenes is that it tells you the progress based on how much data the client ie the browser, has sent to the server. It doesn't actually get a response from the server (as I assume what you are thinking) for how much data the server has received and then displaying the progress to the user. So, if you would think logically and technically, it can not help you in any way. Also, as far as my knowledge goes, sockets are the only way to get a real-time update of the things happening on the server side.

Based on Angular's documentation, progress events can be handled by client, and after doing some searching I cam across server side events - SSE, which is basically sending response headers with connection alive header, and then progress data . I was able to do it, but I still have issues sending and handling custom user events per angular. Here is what that I have.

App component.ts

import { Component ,OnInit} from '@angular/core';
import { CommonService} from './common.service';
import { Observable,Subscription } from "rxjs/Rx";
import 'rxjs/add/operator/timeout';
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css','../../node_modules/bootstrap/dist/css/bootstrap- 
 theme.min.css']
})

export class AppComponent implements OnInit {
 private sseStream: Subscription;
 messages:Array<string> = [];
 progress:number=0;
 totalProgress:number=7;
 constructor(private commonService: CommonService ) { }

 ngOnInit(){
  this.commonService.getHttpObj().subscribe(event=>{
  if(event){
   if(event['loaded']){
   console.log(event['loaded']);
   this.progress=(event['loaded'] / this.totalProgress)*100;
  }
 }
});
}
title = 'Angular4';
}

common.service.ts

import { Injectable } from '@angular/core';
import {HttpRequest} from '@angular/common/http';
import { Observable } from "rxjs/Rx";
import { catchError, map, tap , last} from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
import { HttpEventType } from '@angular/common/http';
const req = new HttpRequest('GET', 'http://localhost:9080/event', {
 reportProgress: true
});

@Injectable()
export class CommonService {

constructor(private http: HttpClient) { }

getHttpObj(){
 return this.http.request(req).pipe(
   map(event => this.getEventMessage(event)),
   tap(message => this.showProgress(message)),
 //   last(), // return last (completed) message to caller
 //  catchError(this.handleError())
 );

};

private getEventMessage(event: any) {
switch (event.type) {
  // case HttpEventType.Sent:
  //   return `Uploading file `;

  case HttpEventType.UploadProgress:
    // Compute and show the % done:
    const percentDone = Math.round(100 * event.loaded / event.total);
    return `File  is ${percentDone}% uploaded.`;

  case HttpEventType.Response:
    return `Complete`;
  case HttpEventType.User:
    return event;
  case HttpEventType.UploadProgress:
    return `${JSON.stringify(event)}`;
  case HttpEventType.DownloadProgress:
    return event;        
  default:
    return event;
 }
}

showProgress(a:any){
  //console.log(a);
  return a;
 }



 private handleError<T> () {
  return (error: any): Observable<T> => {

  // TODO: send the error to remote logging infrastructure
 //    console.error('error'); // log to console instead

   // TODO: better job of transforming error for user consumption
 //    console.log(`${error.message}`);

  // Let the app keep running by returning an empty result.
    return null;
  };
  }
 }

app.component.html

`<div class="container">
  <div style="text-align:center">
  <h1>
  Welcome to {{title}}!!
 </h1>
 <input type="text" [(ngModel)]="test">
 <p>{{test}}</p>
 </div>
 <div class="progress"> 
   <div class="progress-bar bg-success" [ngStyle]="{'width':progress + '%'}"></div>
 </div>
 </div>  `

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'
import { AppComponent } from './app.component';
import { ServerComponent } from './server/server.component';
import { ServersComponent } from './servers/servers.component';
import { HttpClientModule } from '@angular/common/http';
import {CommonService } from './common.service';
import { HttpModule } from '@angular/http';
@NgModule({
 declarations: [
 AppComponent,
 ServerComponent,
 ServersComponent
  ],
 imports: [
  BrowserModule,
  FormsModule,
  HttpClientModule,
  HttpModule
  ],
  providers: [CommonService],
  bootstrap: [AppComponent]
 })
export class AppModule { }

server.js

var express=require('express');
var app=express();
app.listen(9080);

app.get('/event',(req,res)=>{

res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });


        setTimeout(() => {
        res.write( "\n") ;
        setTimeout(() => {
            res.write("\n") ;
            setTimeout(() => {

                res.write( "\n") ;
                setTimeout(() => {
                    res.write( "\n") ;
                    setTimeout(() => {
                        res.write( "\n") ;
                        res.write(JSON.stringify({})) ;
                        res.end();
                        },
                        2000);
                    },
                    2000);
                },
                2000);
            },
            2000);
        },
        2000);


 [enter image description here][1]});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM