Наблюдаемые объекты Angular2 против промисов

В настоящее время я разрабатываю веб-приложение, которое должно загружать набор данных из базы данных SQL (например, некоторых сотрудников или рабочие планы). Каждый раз, когда вы направляетесь к компоненту и обновляете данные, они будут отправлены на сервер и вернут какое-то сообщение об успехе или ошибке.

На данный момент я использую наблюдаемые, но они ведут себя не так, как я хочу. Я подписываюсь на наблюдаемое, получаю свои данные и отписываюсь (я тоже не знаю, где отписаться. В onDestroy или в части Complete моего подписчика?). Но каким-то образом он все еще асинхронен, поскольку выполнение кода продолжается до получения всех данных, что вызывает сбои в моем приложении.

Вот пример моей реализации:

Компонент сотрудника:

getEmployees(department: any){

this.employeesSub = this.employeeManagementService.getEmployees(department).subscribe(
          //Sucess
          data => {this.employees = data},
          //Error
          err => this.logger.error(err),
          //Complete
          () => {this.logger.log('done loading');
                }
    );
}
  ngOnInit(){

    this.selectedDepartment = this.ccs.getSelectedDepartment();
    //Does the same type of request as getEmployees()
    this.getDepartments();
    this.paramSub = this.route.params.subscribe(
        //Success    
        params => {    
            //doStuff
            }
        },
        //Error
        err => this.logger.error(err),
        //Complete
        () => {}
    );
}
  ngOnDestroy(){
      this.employeesSub.unsubscribe();
      this.paramSub.unsubscribe();
  }

Служба сотрудников:

getEmployees(department: string): Observable<Employee[]>{
    let method = "getEmployees";
    let body = JSON.stringify({method, department});
    this.logger.log(body);
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    return this.http.post(this.url, body, options)
                    .map((res:Response) =>{ 
                            this.logger.log(res.json());
                            return res.json();
                    }).catch(this.handleError);
}

Я знаю, что это, возможно, часто спрашивали здесь. Но я действительно не уверен в разнице, даже если я буду читать все больше и больше сообщений, я не получу ее. Может ли кто-нибудь занять некоторое время и помочь мне?


person moessi774    schedule 22.08.2016    source источник


Ответы (3)


Отмена подписки немного избыточна, потому что наблюдаемый объект, возвращенный из this._http.xxx(), закрывается после первого события, что в любом случае приводит к отмене подписки.

Чтобы убедиться, что на вашей стороне, вы также можете использовать this._http.xxx().first().subscribe(...). Таким образом, подписка закрывается после первого события, независимо от того, сколько событий намеревается отправить отправитель.

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

Если вы хотите, чтобы код выполнялся после получения данных, вы должны переместить этот код в subscribe(...), map(...) или какой-либо другой наблюдаемый оператор.

person Günter Zöchbauer    schedule 22.08.2016
comment
Спасибо за быстрый ответ. Я изменил свои подписки и добавил .take(1) к каждой из них. Я уже пытался поместить остальную часть моего кода инициализации в часть complete первого подписанного наблюдаемого. Кажется, это работает, но я думаю, что это действительно уродливое решение. Неужели нет другого пути? - person moessi774; 22.08.2016
comment
Я не очень понимаю наблюдаемые операторы. Я думал, что они только для небольших операций с возвращаемым результатом. - person moessi774; 22.08.2016
comment
В них можно вставить любой код. Если вы вызываете другой метод из обратного вызова, он все еще мал, но этот метод может выполнять огромное количество кода. Я бы сказал, просто не беспокойтесь о количестве кода, выполняемого в наблюдаемых операторах. Чтобы сохранить ответственность браузера, всегда полезно не выполнять ненужную дорогостоящую работу внутри или вне операторов. - person Günter Zöchbauer; 22.08.2016
comment
Например, если я вызываю getDepartments() в onInit(), я просто перемещаю свой код onInit(), который будет следовать за getDepartments() в методе, и вызываю его в операторе .map наблюдаемых отделов, верно? Но мне это кажется немного уродливым, поскольку я перемещаю код onInit куда-то еще. - person moessi774; 23.08.2016
comment
Да, это звучит разумно. - person Günter Zöchbauer; 23.08.2016
comment
Но разве это не уродливый способ программирования? И как мне назвать метод, чтобы он имел смысл? Извините за столько вопросов, но спасибо, что выручаете меня каждый раз :) - person moessi774; 23.08.2016
comment
У асинхронного выполнения есть преимущества (нет потоков, нет условий гонки), но есть и некоторые недостатки. Но так это работает. - person Günter Zöchbauer; 23.08.2016
comment
наблюдаемый объект, возвращаемый из this._http.xxx(), закрывается после первого события? @GünterZöchbauer - person Rafael Reyes; 10.03.2018
comment
@RafaelReyes это идея first() - person Günter Zöchbauer; 10.03.2018
comment
Итак, при одном вызове, который ожидает только одно значение на ответ, как this.http.xxx() узнает, когда закрыть http-соединение с сервером? --вместо того, чтобы держать открытым ожидание возможных других значений с течением времени, как описано в определении Observable. (без использования первого()) @GünterZöchbauer - person Rafael Reyes; 10.03.2018
comment
Сервер закрывает соединение после отправки ответа. - person Günter Zöchbauer; 10.03.2018

Промисы:
Выдает только одно значение за раз.
Вызывает службы без then и catch.
Нельзя отменить.
Не предоставляет никакого оператора.

Observable :
выдает несколько значений в течение определенного периода времени.
Он не вызывается, пока мы не подпишемся на наблюдаемый.
Предоставьте карту, forEach, фильтр, сокращение, повторите попытку и повторите попытку, когда.
Это функция, которая подписывается позже
Lazy

person Lucky    schedule 12.11.2019