No message is arrived at first attempt, but after it works

I use Mercure with Symfony4 and Angular9. On the click event of a button, I publish the Mercure update :

In the component.html :

<button (click)="insertSynonyme()" class="btn btn-default mb-2">Save</button>

In the component.ts :

constructor(
    ...
    private mercureServ: MercureService,
    ...
  ) {
    ...
  }
...
insertSynonyme(){
    const data = {
      old_cle: this.synoForm.value.cle_syno,
      add_synonymes: this.dataSynonyme.oldSynonyme
    };
    // make database update first
    this.generalServ.insertSynonyme(data).subscribe( // calls a Symfony API
      res => {
               this.mercureServ.getServerSentEvent('http://localhost:3000/.well-known/mercure','suggestioncontenu').subscribe(
                   data => {
                        console.log("==================== dans callback de getServerSentEvent depuis component ts, on a data = ", data);
                        this.mercureServ.close();
                   }
               );
             });
 }

The insertSynonyme code :

insertSynonyme(data){
    return this.dataServ.postData(API.insertSynonyme, data);
  }

The postData code :

@Injectable({
  providedIn: 'root'
})
export class DataService {
  constructor(protected http: HttpClient) { }

  postData(url, dataObject): Observable<any> {
    const httpOptions = {
      headers: new HttpHeaders({
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + sessionStorage.getItem('token')
      })
    };
    return this.http.post(ws_URL.concat(url), dataObject, httpOptions).pipe(retry(1));
  }
  ...
}

The Symfony API called :

use AppUtilsConstantSrv;
use FOSElasticaBundleElasticaClient;
use FOSElasticaBundleFinderFinderInterface;
use FOSElasticaBundleFinderTransformedFinder;
use FOSRestBundleControllerAnnotations as Rest;
use FOSRestBundleControllerAnnotationsQueryParam;
use FOSRestBundleRequestParamFetcher;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationJsonResponse;
use AppServiceSearchService;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationSessionSessionInterface;
use SymfonyContractsTranslationTranslatorInterface;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyComponentMercurePublisherInterface;
use SymfonyComponentMercureUpdate;

class SearchController extends AbstractController
{
    ...
    /**
     * @RestPost("/api/insertUpdateSynonyms", name ="api_insert_update_synonyms")
     * @RestRequestParam(name="old_cle", nullable=true)
     * @RestRequestParam(name="add_synonymes", nullable=true)
     * @RestRequestParam(name="new_cle", nullable=true)
     * @RestRequestParam(name="new_synonymes", nullable=true)
     *
     * @return Response
     */
    public function insertUpdateSynonyms(ParamFetcher $paramFetcher, SearchService $searchService, PublisherInterface $publisher)
    {
        try {
            $searchService->insertUpdateSynonyms($paramFetcher);
            $update = new Update(
                'suggestioncontenu',
                json_encode(['etat' => 'OutOfStock'])
            );
            $subscriber_id = $publisher($update);
            return new Response('');
        } catch (Exception $e) {
            return new Response('');
        }
    }

}

The MercureService in mercure.service.ts :

import { Injectable, NgZone } from "@angular/core";
import { Observable } from "rxjs";

@Injectable({
    providedIn: 'root'
})
export class MercureService {

    eventSource: EventSource;

    constructor(private zone: NgZone) { }

    private getEventSource(url: string, topic: string): EventSource {
        const urls = new URL(url);
        urls.searchParams.append('topic', topic);
        return new EventSource(urls.toString());
    }

    /**
     * return the event source stream
     */
    getServerSentEvent(url: string, topic: string): Observable<MessageEvent> {

        return new Observable(observer => {

            this.eventSource = this.getEventSource(url, topic);

            this.eventSource.onopen = op => {
                console.log("--------------------- connex entre mercure et angular est ouverte");
            }

            this.eventSource.onmessage = event => {
                const data = event.data;
                const toSend = data.substring(data.indexOf('GMT') + 3, data.length - 1).trim();
                console.log("================= event data depuis angular service = ", toSend);
                this.zone.run(() => observer.next(toSend));
            };

            this.eventSource.onerror = err => {
                console.log("================ erreur : ", err);
            }

        });
    }

    close() {
        if (this.eventSource) {
            this.eventSource.close();
        }
    }

}

At runtime, when I click the button for the first time then no data is sent, I do not see any console log showing ================= event data depuis angular service; but when I click the button again then data is sent, and console log is displaying with the data; and even if I reclick the button many times then data is sent. So why are there no data sent at the first click ?

Source: Symfony4 Questions

Was this helpful?

0 / 0

Leave a Reply 0

Your email address will not be published. Required fields are marked *