обработка задержек при извлечении данных angular

Во-первых, я не программировал более десяти лет (бывший Java-разработчик), поэтому просто знакомлюсь с Angular 4 в качестве хобби, но мне не хватает базового понимания. Я искал обработку задержки извлечения данных с помощью наблюдаемых, но не получил никаких релевантных результатов. Надеюсь, кто-то здесь может помочь и объяснить. Он вращается вокруг следующего кода TypeScript (см. также встроенные комментарии):

Удаленная служба данных

export class RemoteDataService {
private headers = new Headers({ 'Content-Type': 'application/json' });
constructor(private http: Http) { }

 public getData(url)  {
  return this.http.get(url)
  .map(
    (response: Response) => {
      const data = response.json();
      return data;
    }
  )
 }
}

СтатьиСервис

export class ArticleService implements OnInit {
_articles: Article[];

constructor(private _remoteDataService: RemoteDataService) {
  this.onGet();
  console.log(JSON.stringify(this._articles)) **//<- this._articles is null** 
  setTimeout(()=> console.log(JSON.stringify(this._articles + "////")), 3000) 
  } **//<- but if I wait 3 seconds this._articles is set to data elements**

 public onGet() {
   this._remoteDataService.getData('./assets/articles.json')
   .subscribe(
   (articles: any[]) => {
    this._articles = articles, 
    console.log(this._articles) **//<- this_.articles is set**
    },
    (error) => console.log(error))

    //console.log(this._articles) **//<- if I uncomment this_.articles is null, huh?**
  }
 }

Выход:

article.service.ts:34 "не определен////"

article.service.ts:46 (20) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…} , ?>{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

article.service.ts:35 "[объект Объект],[объект Объект],[объект Объект],[объект >Объект],[объект Объект],[объект Объект],[объект Объект],[объект Объект],[ объект >Объект],[объект Объект],[объект Объект],[объект Объект],[объект Объект],[объект >Объект],[объект Объект],[объект Объект],[объект Объект],[объект Объект] ,[объект >Объект],[объект Объект]////"

Мои вопросы:

1) Почему в методе onGet() this._articles не устанавливается в ноль?

2) Как обычно обрабатывается задержка данных, потому что мой компонент, вызывающий службы, дает сбой, потому что статьи еще не установлены?


person Community    schedule 23.08.2017    source источник


Ответы (3)


1) Вызов, который вы делаете для своей службы, происходит асинхронно, что означает, что вызов выполняется в другом потоке, но onGet() продолжает выполняться. this._articles еще не установлен, когда вы входите в консоль.

2) Ого, это большой вопрос, и ответ во многом зависит от того, чего вы пытаетесь достичь. Во-первых, использование setTimeout() — плохая практика. Вам нужно спроектировать свои компоненты таким образом, чтобы они могли работать без каких-либо данных. Если ломается ваш шаблон, оператор безопасной навигации может пригодиться. Если вы предоставите более подробную информацию, я был бы рад помочь.

person dockleryxk    schedule 23.08.2017
comment
функция setTimeout() предназначена только для тестирования. Я понимаю асинхронность, чего я не понимаю, так это того, почему он был установлен на ноль. (Последний комментарий в коде) - person ; 24.08.2017
comment
Это потому, что код не выполняется в том порядке, в котором он написан. Функция подписки вызывается, но сразу после этого вызывается console.log, то есть до завершения вызова. - person dockleryxk; 24.08.2017
comment
спасибо, я понял всю последовательность инструкций, однако я до сих пор не понимаю, почему консоль выводит this_.articles как жизнеспособный объект, а затем сразу после этого выводит this._articles как null. Мне казалось, что каждый раз печаталось бы null, затем по таймауту значение наконец печаталось бы. Теперь я перешел к новой проблеме, но она все еще очень неясна для меня. - person ; 24.08.2017
comment
Просто потребуется некоторое время, чтобы привыкнуть. Просто прочитайте несколько статей, и это поможет. Примечание: делайте как можно меньше в конструкторах компонентов. Вместо этого вы должны выполнять работу в ngOnInit(). - person dockleryxk; 24.08.2017

Думаю, я понял это. . . извините, что беспокою всех.

Я поместил это в свой сервис статей

articleHasChanged = new Subject<Article[]>();

это добавило этот код в мой компонент

  private _articleSubscription: Subscription;

this._articleSubscription = this._articleService.articleHasChanged.subscribe({
  next: (articles) => {
    console.log("Time to get the article");
    this._articleService.getArticleByID(this.id);
    console.log(this.diagnostic)
  }
}
)

Кажется, это работает

person Community    schedule 23.08.2017

Вам нужно больше узнать о подписках и наблюдаемых объектах Angular. Потому что они работают не так, как вы думаете. Вероятно, это хорошая статья для этого, но вам следует поискать . Я думаю, что это официальная документация по API

Это очень просто понять. Всякий раз, когда вы делаете запрос в своем приложении. Приложению не нужно ждать, пока запрос завершится. Это очень похоже на то, как работает ваш браузер. Вы вводите URL-адрес в свой браузер и делаете другие вещи, пока загружается страница, а затем, когда вы видите, что браузер закончил загрузку, вы возобновляете и используете страницу. Когда вы используете this.http.get(url), браузер обрабатывает запрос за пределами вашей текущей области приложения. Таким образом, следующие блоки кода будут продолжать выполняться, пока браузер делает запросы и ожидает ответа. Поэтому, когда выполняется любой другой код, запрос еще не завершил загрузку, что происходит очень быстро, в то время как завершение загрузки запроса может занять несколько секунд.

Когда вы используете return this.http.get(url).map() - вы возвращаете наблюдаемую, которая возвращается сразу после вызова запроса - когда от сервера не было ответа, так как он все еще загружается.

.subscribe(
   (articles: any[]) => {
    this._articles = articles, 
    console.log(this._articles) **//<- this_.articles is set**
    },
    (error) => console.log(error))

Эта часть кода подписывается на наблюдаемое. Таким образом, когда запрос завершает загрузку, любой код в subscribe() выполняется в зависимости от того, был ли запрос успешным. К настоящему времени будет выполнен весь код в области public onGet() {}, кроме .subscribe(). Он будет выполнен только после завершения загрузки запроса.

Вы никогда не узнаете, сколько времени займет загрузка запроса, поэтому использование setTimeout() будет бесполезным. Поэтому лучше всего дать компьютеру знать, когда загрузка запроса завершена, и именно тогда вы используете Observables.

person Community    schedule 23.08.2017