Почему наблюдаемая отправка старых значений - PullRequest
0 голосов
/ 26 сентября 2019

Я создал службу, которая отправляет запрос бэкэнду и делает результат доступным для компонента через наблюдаемую область.

export class QuestionManagementService {

  questionsArray$: Observable<Result>;
private questionsArraySubject: BehaviorSubject<Result>; //to send list of questions
...
constructor(private http: HttpClient, private helper:HelperService, private bs:WebToBackendInterfaceService, private loaderService:LoaderService) {
    this.questionsArraySubject = new BehaviorSubject<Result>(new Result('initial',{})); //A Subject can act both as an Observable and an Observer
    this.questionsArray$ = this.questionsArraySubject.asObservable(); //create Observable. Other components can subcribe to it now to get notifications/values

...
}

//this method sends the request to network via another `bs` service. The request is sent using `http.post` 

getQuestions(questionFilter:GetQuestionsfilter){
    console.log("In QuestionManagementService: getQuestions");
    let observable:Observable<HttpEvent<any>> = this.bs.getQuestions(questionFilter);
    let subscription:Subscription =  observable.subscribe((ev:HttpEvent<any>)=>{
          if(ev.type === HttpEventType.Response) { //null means that the response wasn't an HttpResponse but probably some internal Rxjs event (eg type 0)
            let response= <HttpResponse<any>>ev;
            console.log("http response received: ",response);
            //should remove the token from storage

            console.log('response body from server: ',ev.body);
            let isResponseStructureOK: boolean = this.helper.validateServerResponseStructure(ev.body);
            if (isResponseStructureOK) {
              console.log("response structure is OK");
              let response: ServerResponseAPI = ev.body;
              let result:string = response.result;
              console.log("result is : " + result);
              /*if result could be success or error*/
              /*additionalInformation is a string and the string contains a valid json which has array of questions
              in format {"questions-list":[{"tag":"some tag1","description":"some description1"},{{"tag":"some tag2","description":"some description2"},...]}
              */

              let message:string = response['additional-info'];
              console.log("message is "+message);

              if(result === "success") {
                let jsonQuestionList: string = response['additional-info'];
                console.log("jsonQuestionList response as string: ", jsonQuestionList);
                //let jsonQuestions: PracticeQuestionsListAPI = JSON.parse(jsonQuestionList);
                //console.log("jsonQuestion array:", jsonQuestions);
                //this.questionsArraySubject.next(jsonQuestions['questions-list']);
                this.questionsArraySubject.next(new Result('success', response["additional-info"]));
              } else {
                this.questionsArraySubject.next(new Result('error', response["additional-info"]));
              }
            }
            else {
              /**
               * If something goes wrong, send error rather than send next with result="error"
               */
              console.log("received incorrect response structure from server: ", ev.body);
              //TODOM - need to change hard coded responses and pick them from a config or global variable.
              this.questionsArraySubject.error(new Result('error',"Invalid response structure from server"));
            }
          }
          else {
            console.log("not response. ignoring");
          }
        },
        (error:ServerResponseAPI)=>{/*web to backend service will send error in ServerResponseAPI format. This is what handleError throws*/
          console.log("got error from the Observable: ",error);
          this.questionsArraySubject.error(new Result('error',error['additional-info']));
        },
        ()=>{ //observable complete
          console.log("observable completed")


        });


  }
}

Следующий компонент подписывается на эту службу.

export class PraticeQuestionListComponent implements OnInit, OnDestroy {
questions: PracticeQuestionsListAPI; //the result from observable will be stored here.
questionListSubscription:Subscription; //reference of the subscription

ngOnDestroy(): void {
    console.log("destroying component. unsubscribing");
    this.questionListSubscription.unsubscribe()
  }
//on initialisation, I subscribe to the observable

  ngOnInit(){
    console.log("in question list on init. question is ",this.questions);
   ...
    this.questions= new PracticeQuestionsListAPI(new AdditionalPagingInfo("",new PartitionInfo(0,0)),
      []);

 let tagSubscription = this.questionManagementService.getSupportedTags(new TagId("coding"));

    console.log("subscribing to question mgmt service");
    this.questionListSubscription = this.questionManagementService.questionsArray$.subscribe((result:Result)=>{
      console.log('received result from question mgmgt service - array observable',result);
      if(result.result === "success") { //received response from server
        let questionList = JSON.parse(result.additionalInfo) as PracticeQuestionsListAPI;
        console.log("got list of questions value ", questionList);
        this.questions['pagination-info'] = questionList['pagination-info'];
        this.questions['questions-list'] = questionList['questions-list'];
        /*
       0 length of questions-list means no questions.
       this could be response from the server indicating that there are no more questions
         */
        /*
        * the server indicates that there are no more questions by either sending empty question list or by sending
        * 0 values for pagination state and partition info
        */
        if (questionList["questions-list"].length !== 0) { //server has send list of questions
          this.questions['pagination-info']['page-state'] = questionList['pagination-info']['page-state'];
          this.questions['pagination-info']['partition-info'] = questionList['pagination-info']['partition-info'];
          this.questions['questions-list'] = questionList['questions-list'];
          console.log("previous question filter is ",this.questionsFilter);

          this.questionsFilter["pagination-info"]["page-state"]=questionList["pagination-info"]["page-state"];
          this.questionsFilter["pagination-info"]["partition-info"].month=questionList["pagination-info"]["partition-info"].month;
          this.questionsFilter["pagination-info"]["partition-info"].year=questionList["pagination-info"]["partition-info"].year;

          console.log("new question filter is ",this.questionsFilter);
          //TODOM - maybe this assignment below was causing memory leak. So changed this as above
          //this.questionsFilter['pagination-info'] = questionList['pagination-info'];
          this.lastPage = false; //the server indicates that there are no more questions by sending these values (no paging state and no partition info)
          if (this.questions['pagination-info']['page-state'].length == 0 &&
            this.questions['pagination-info']['partition-info'].year == 0 &&
            this.questions['pagination-info']['partition-info'].month == 0) {
            this.lastPage = true;
          } else {//if the list is empty then there are no (more) questions for the selected tag
            this.lastPage = false;

          }
        } else {
          this.lastPage = true; //Don't show next button if there are no questions.
          this.showDialog(new PracticeQuestionListContext("Reached end of the search. No more results available", new PracticeQuestionListAdditionalInfo()));
        }
      } else {
        //TODOM - I should probably display the error in case there is an error from the server
        console.log("ignoring value");
      }
    },
    (err:Result)=>{
        console.log("received error from QuestionArray observable",err);
        //TODOM - probably should change the name of DialogContext to Component specific additional context
        this.showDialog(new PracticeQuestionListContext(err.additionalInfo,new PracticeQuestionListAdditionalInfo()));
      },
      ()=>{
      console.log("question mgmt service, questionarray observable completed.");
      });
  }
}

Проблема, с которой я сталкиваюсь, заключается в том, что, если я впервые посещаю компонент, я получаю значения из наблюдаемого после выбора элементов в пользовательском интерфейсе (ожидаемое поведение).Затем я захожу на домашнюю страницу приложения, компонент уничтожается (опять же, ожидаемое поведение).Затем, если я снова посещаю компонент, наблюдаемая отправляет старые значения (с первого посещения), даже если я не выбрал пользовательский интерфейс.

Почему наблюдаемая отправляет старые значения и как я могу остановить егоделая это?Я создал еще один вопрос в SO с картинками, которые могли бы лучше объяснить сценарий

угловой компонент сохраняет старое значение, может быть, потому что наблюдаемая повторно отправляет прошлые данные

...